Моя пользовательская функция с вложенными операторами if else неправильно оценивает векторные входные данные в R — пожалуйста, помогите

#r #vector #if-statement

#r #вектор #if-statement

Вопрос:

Я пытаюсь создать функцию, которая показывает, сколько «человеко-лет» человек внес в данную возрастную группу за определенный период. Если человек жив в течение указанного интервала, он вносит свой вклад в временной интервал. Например, для возрастной группы 0-1 человек, который попал под наблюдение в возрасте 0,5 года и ушел в возрасте 3 лет, внесет 0,5 года в число человеко-лет для возрастной группы 0-1.

Я смог успешно запустить этот код через цикл for, но это занимает целую вечность, поэтому я пытаюсь вместо этого реализовать векторную функцию. Функция отлично работает для отдельных записей, но не может обрабатывать векторы, которые я ей передаю, выдавая ошибку: «… условие имеет длину> 1, и будет использоваться только первый элемент»

Функция, которую я написал, выглядит следующим образом:

 pyears01.smm <- function(ageent, ageleave) {
if ( is.na(ageent) | is.na(ageleave) ) 
    {NA} else
if( ageent > 1 )
    {0} 
if ( ageent <= 1 amp;amp; ageleave > 1 ) 
    {1-ageent} else
if( ageent <= 1 amp;amp; ageleave <= 1 ) 
    {ageleave-ageent} 
}
 

который отлично работает для оценки следующего:

 pyears.smm(0,5)
[1] 1
pyears.smm(0.5,0.75)
[1] 0.25
pyears.smm(2,3)
[1] 0
 

но неправильно оценивает NAs:

 > pyears.smm(NA,NA)
[1] 0
> pyears.smm("NA",5)
[1] 0
 

и неправильно обрабатывает векторы:

 x <- c(0,0.5,2,5)
y <- c(5,0.75,3,NA)
z<- pyears.smm(x,y)
Warning message:
In if (!is.na(ageent) amp; ageent <= 1 amp; !is.na(ageleave) amp; ageleave >  :
  the condition has length > 1 and only the first element will be used
> z
[1]  1.0  0.5 -1.0 -4.0
 

Я читал, что elseif принимает векторы, в то время как операторы if, подобные этому, могут оценивать только отдельные элементы, но у меня есть несколько слоев вложенных операторов if, поэтому я не уверен, как это исправить. Любые предложения будут оценены. Спасибо!

Ответ №1:

Получаемое вами предупреждающее сообщение является распространенным, особенно если вы переходите с другого языка программирования. Вы ищете ifelse() функцию, которая работает с векторами. Как указано в предупреждающем сообщении, оно оценило только первое условие. Вот ifelse() версия вашего кода:

 pyears01.smm2 <- function(ageent, ageleave){
    ifelse(is.na(ageent) | is.na(ageleave), NA
    , ifelse(ageent > 1,0
    , ifelse(ageent <= 1 amp; ageleave > 1, 1 - ageent, ageleave - ageent)))
}

> pyears01.smm2(NA, NA)
[1] NA
> pyears01.smm2(NA, 5)
[1] NA
> x <- c(0,0.5,2,5)
> y <- c(5,0.75,3,NA)
> pyears01.smm2(x,y)
[1] 1.00 0.25 0.00   NA
 

Если вы используете Google или ищете в SO различия между if else и ifelse() , я уверен, вы найдете что-то хорошее. Вот одна ссылка, которая поднялась на вершину: http://rwiki.sciviews.org/doku.php?id=tips:programming:ifelse

Комментарии:

1. Большое спасибо! Это сработало — я не сталкивался с форматом для вложения в ifelse, но понял, что это проблема.

Ответ №2:

Векторизованная форма an if else construct ifelse (не elseif). Однако для этого упражнения это вам не нужно. Вместо этого используйте pmax и pmin , чтобы получить (поэлементно) верхнюю и нижнюю границы интервала экспозиции для каждого наблюдения, а также для обработки случая, когда возраст при входе и выходе полностью выходит за пределы интервала.

 pyears01.smm <- function(ageent, ageleave)
pmax(0, pmin(ageleave, 1) - pmax(ageent, 0))
 

Комментарии:

1. Спасибо — очень полезно для такого рода вещей.

Ответ №3:

Проблема, которую вы пытаетесь решить, уже была решена в двух пакетах, о которых я знаю: «выживание» и «epi». Вы (без необходимости) заново изобретаете диаграмму лексики.