tapply — создание NA?

Я пытаюсь рассчитать среднее количество уникальных фруктов на человека (данные моей обычной практики). Это отлично работает с обеими этими строками кода:

with(df, tapply(fruit, names, FUN = function(x) length(unique(x))))->uniques
sum(uniques)/length(unique(df$names))

aggregate(df[,"fruit"], by=list(id=names), FUN = function(x) length(unique(x)))->d1
sum(d1$x)/length(unique(df$names))

Моя проблема в том, что когда я использую код на своих реальных данных, он не работает. Мои настоящие данные — это данные о назначении, где я хочу получить среднее количество уникальных лекарств на человека. С помощью кода tapply он создает совершенно новые идентификаторы пациентов, которых нет в исходном файле df. он также вернул 1000 значений NA. В моем столбце id нет пропущенных значений, а в столбце Drug_code также нет

with(dt3, tapply(drug_code, id, FUN = function(x) length(unique(x))))->uniques    

head(uniques)
                   uniques
Patient HAI0000001      NA
Patient HAI0000003      NA
Patient HAI0000008      NA
Patient HAI0000010      NA
Patient HAI0000014      NA
Patient HAI0000020      NA

table(dt3$id=="Patient HAI0000001")  ##checking to see if HA10000001 occurs in original df. the dim of df are 228954 rows and 5 cols

FALSE 
228954

Для совокупного кода я получаю сообщение об ошибке:

aggregate(dt3[,"drug_code"], by=list(id=id), FUN = function(x) length(unique(x)))->d1

Error in aggregate.data.frame(as.data.frame(x), ...) : 
  arguments must have same length

Я не понимаю, что происходит. Мои реальные данные аналогичны данным моей практики в том, что они имеют столбец идентификатора и столбец наркотики/фрукты. нет пропущенных данных ни в одном df. Я знаю, что lapply лучше для фреймов данных, но мне не обязательно нужен df. И в любом случае код tapply работает с практическими данными, которые представляют собой df. Кто-нибудь знает, что здесь происходит?

Практика ДФ:

 names<-as.character(c("john", "john", "john", "john", "john", "mary", "mary","mary","mary","mary", "jim", "sylvia","ted","ted","mary", "sylvia", "jim", "ted", "john", "ted"))
dates<-as.Date(c("2010-07-01",  "2010-09-01", "2010-11-01", "2010-12-01", "2011-01-01", "2010-08-12",  "2010-11-11", "2010-05-12",  "2010-12-03", "2010-07-12",  "2010-12-21", "2010-02-18",  "2010-10-29", "2010-08-13",  "2010-11-11", "2010-05-12",  "2010-04-01", "2010-05-06",  "2010-09-28", "2010-11-28" ))
fruit<-as.character(c("kiwi","apple","banana","orange","apple","orange","apple","orange", "apple", "apple", "pineapple", "peach", "nectarine", "grape", "melon", "apricot", "plum", "lychee", "watermelon", "apple" ))
df<-data.frame(names,dates,fruit) 

пример реальных данных:

head(dt3)
        id         quantity   date_of_claim drug_code  index
1  Patient HAI0000560        1    2009-10-15 R03AC02 2010-04-06
2  Patient HAI0000560        1    2009-10-15 R03AK06 2010-04-06
3  Patient HAI0000560       30    2009-10-15 R03BB04 2010-04-06
4  Patient HAI0000560       30    2009-10-15 A02BC01 2010-04-06
5  Patient HAI0000560       50    2009-10-15 M02AA15 2010-04-06
6  Patient HAI0000560       30    2009-10-15 N02BE51 2010-04-06

person user2363642    schedule 18.07.2013    source источник


Ответы (2)


В вашем случае вы запрашиваете одно число: среднее значение всех отдельных длин определенного вектора (unique(fruits)) в идентификаторе пациента. Это показывает вам сначала индивидуальные уникальные подсчеты, а затем средний результат функции:

> with(df,  tapply(fruit, names, function(x) length(unique(x)) ))
   jim   john   mary sylvia    ted 
     2      5      3      2      4 
> mean ( with(df,  tapply(fruit, names, function(x) length(unique(x)) )) )
[1] 3.2

Я бы прокомментировал, что ваш тест на включение определенного значения в ваш код выше имел завершающий пробел, который мог вызвать проблемы. "string " не будет равно "string". Я поместил копию использования функции обрезки в pkg::gdata в моем файле .Rprofile, чтобы мне было проще справиться с этой возможностью.

person IRTFM    schedule 18.07.2013
comment
Привет, Двин, спасибо за ответ. Конечный пробел был просто ошибкой с моей стороны при передаче кода, это не причина проблемы. Использование функции среднего лучше, чем то, что я делал, но проблема не в этом. Проблема в тапе. Он создает все эти Nas там, где их быть не должно. он отлично работает с фиктивными данными, я не могу понять, почему он не будет работать с реальными данными. фиктивные данные аналогичны реальным данным в том смысле, что все переменные в коде tapply являются переменными-факторами. Начнем с того, что в реальных данных нет Nas, поэтому я не знаю, почему tapply их создает. - person user2363642; 18.07.2013
comment
подождите - думаю, я кое-что понял - - следите за обновлениями - person user2363642; 18.07.2013
comment
Если бы вы опубликовали dput(head(dt3)), мы могли бы предложить лучшую помощь. - person IRTFM; 18.07.2013
comment
хорошо, вот ответ! Я сделал свой настоящий DF (dt3), вырезав его из другого большего родительского DF. следовательно, уровни id в dt3 остались такими же, как и в родительском DF. вот откуда все Nas. Решение довольно простое.........сумма(x, na.rm=TRUE)/длина(unique(dt3$hai_dispense_number)). Я придерживаюсь этого - среднее (x, na.rm = TRUE) занимает слишком много времени! Спасибо за помощь! - person user2363642; 18.07.2013
comment
Еще раз спасибо DWin - когда я сделал вывод сюда, решение стало еще более очевидным. - person user2363642; 18.07.2013

Я мог что-то упустить, но разве здесь не сработает простой tapply? Строка ниже вычисляет количество разных фруктов на человека.

x=tapply(df$fruit,df$names,function(x){length(unique(x))})

И тогда mean(x) даст вам среднее значение по людям?

person slammaster    schedule 18.07.2013
comment
Привет slammaster - спасибо за ответ. см. мой ответ Двину, средняя функция - это не мой вопрос - вопрос касается того, почему tapply создает Nas в моем реальном df. Не могу понять, почему это происходит. - person user2363642; 18.07.2013
comment
Привет еще раз, slammaster - я понял это - см. Решение, которое я дал в своем разговоре с DWin. Как ни странно, среднее (x, na.rm=TRUE) выполнялось слишком долго, поэтому я придерживаюсь суммы/длины. Спасибо за вашу помощь! - person user2363642; 18.07.2013