2014-01-15 1 views
1

Я понимаю, что есть ряд вопросов по этой теме, но я не смог решить свою проблему, просмотрев различные ответы. У меня есть ФР - экстракт которого прилагается ниже:Разбиение df по факторам, применение функции и возврат комбинированного df в r

ID = as.factor(c("1","1","1","1","1", 
       "2","2","2", 
       "3","3","3","3", 
       "4","4","4","4","4")) 
AdDate = c("2010-03-04", "2010-04-05", "2011-01-23", "2011-03-20", "2012-07-08", 
      "2010-12-02", "2011-05-17", "2011-09-11", 
      "2010-04-11", "2010-05-15", "2011-02-22", "2011-09-23", 
      "2009-10-04", "2010-02-15", "2010-08-17", "2011-06-20", "2012-04-08") 
OpofInterest = c("FALSE", "FALSE", "TRUE", "FALSE", "FALSE", 
       "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", "FALSE") 
df = data.frame(ID, AdDate, OpofInterest) 

Что я тогда хочу сделать, это разделить ФР по идентификатору в ряд dataframes (4 в этом примере), а затем применить функцию ниже назначить, будут ли другие эпизоды (каждая строка) до (до операции), одна и та же (за операцию) или после операции интереса (после операции) для каждого человека (ID) на основе AdDate. Я новичок в R и программировании и создал функцию ниже. На самом деле, у меня есть тысячи идентификаторов и эпизодов и около 80 столбцов, поэтому я не могу индивидуально подмножать и применять функцию, которую я должен работать после некоторой настройки.

prepostassignment <- function (df) { 

df_OpofInterest = subset(df,(df["OpofInterest"] == "TRUE")) 

for (i in 1:nrow(df)) { 

if (df$AdDate[i] < df_OpofInterest$AdDate) { 
    df$Pre_Post_Assignment[i] = "Pre" 

} else if (df$AdDate[i] == df_OpofInterest$AdDate) { 
    df$Pre_Post_Assignment[i] = "Per" 

} else if (df$AdDate[i] > df_OpofInterest$AdDate) { 
    df$Pre_Post_Assignment[i] = "Post" 

    } 
} 
} 

Я играл вокруг с помощью, tapply, агрегат, ddply и не могу придумать решения. Кроме того, я получаю следующее сообщение об ошибке при использовании функции на ручное подмножестве:

отсутствующего значения где TRUE/FALSE необходимого

Я прочитал на этом, как хорошо, но не могу понять, где он собирается неправильно в моем конкретном коде

То, что я хочу, чтобы в конечном итоге заключается в следующем:

ID = as.factor(c("1","1","1","1","1", 
       "2","2","2", 
       "3","3","3","3", 
       "4","4","4","4","4")) 
AdDate = c("2010-03-04", "2010-04-05", "2011-01-23", "2011-03-20", "2012-07-08", 
      "2010-12-02", "2011-05-17", "2011-09-11", 
      "2010-04-11", "2010-05-15", "2011-02-22", "2011-09-23", 
      "2009-10-04", "2010-02-15", "2010-08-17", "2011-06-20", "2012-04-08") 
OpofInterest = c("FALSE", "FALSE", "TRUE", "FALSE", "FALSE", 
       "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", "FALSE") 
Pre_Post_Assignment = c("Pre", "Pre", "Per", "Post", "Post", 
         "Pre", "Per", "Post", 
         "Pre", "Pre", "Per", "Post", 
         "Pre", "Pre", "Per", "Post", "Post") 
df_new = data.frame(ID, AdDate, OpofInterest, Pre_Post_Assignment) 

Любая помощь будет принята с благодарностью.

Спасибо.

+0

Что такое 'df_OpofInterest' и' df_TAVI' в вашем втором куске кода? – josliber

+0

Извинения, df_TAVI должен был быть df_OpofInterest. Я подмножал «Op of interest», чтобы получить AdDate для использования в функции – sgurwin

+0

Почему вы начинаете с столбцов класса 'character' (которые затем преобразуются в' factor')? Не должен ли ID быть «целочисленным», дата «Date», OpofInterest «логична»? –

ответ

3

Это классический анализ split-apply-comb. Вот вариант использования data.table:

df = data.frame(ID, AdDate, OpofInterest, stringsAsFactors=FALSE) 
df$OpofInterest <- as.logical(df$OpofInterest) 
library(data.table) 
dt <- data.table(df) 
dt[, 
    cbind(
    .SD, 
    Pre_Post_Assignment= 
     ifelse(
     AdDate < AdDate[OpofInterest], 
     "Pre", 
     ifelse(AdDate == AdDate[OpofInterest], "Per", "Post" 
    ))), 
    by=ID] 
#  ID  AdDate OpofInterest Pre_Post_Assignment 
# 1: 1 2010-03-04  FALSE     Pre 
# 2: 1 2010-04-05  FALSE     Pre 
# 3: 1 2011-01-23   TRUE     Per 
# 4: 1 2011-03-20  FALSE    Post 
# 5: 1 2012-07-08  FALSE    Post 
# 6: 2 2010-12-02  FALSE     Pre 
# 7: 2 2011-05-17   TRUE     Per 
# 8: 2 2011-09-11  FALSE    Post 
# 9: 3 2010-04-11  FALSE     Pre 
# 10: 3 2010-05-15  FALSE     Pre 
# 11: 3 2011-02-22   TRUE     Per 
# 12: 3 2011-09-23  FALSE    Post 
# 13: 4 2009-10-04  FALSE     Pre 
# 14: 4 2010-02-15  FALSE     Pre 
# 15: 4 2010-08-17   TRUE     Per 
# 16: 4 2011-06-20  FALSE    Post 
# 17: 4 2012-04-08  FALSE    Post 

Вы также можете использовать ddply для этого. Мясо фактического расчета представляет собой два вложенных заявления ifelse. Второй аргумент [.data.table - это список столбцов, которые мы хотим на выходе, в дополнение к столбцу split/groupn (ID здесь). Переменная .SD является специальной переменной data.table, которая содержит все столбцы в группе, на которые не ссылаются аргумент by (здесь он будет содержать AdDate и OpofInterest). We cbind наш дополнительный вектор для .SD, чтобы создать наш новый результат с дополнительной колонкой.

Несколько других примечательных пунктов:

  1. я преобразовал даты, чтобы строки для сравнения работы
  2. я преобразовал OpofInterest логические

Наконец, об ограничении ответственности, в то время как типа анализа здесь выполняется split-apply-comb, реализация за кулисами в data.table не разбивается и применяется, скорее, она подмножества и итерации (я отмечаю это здесь, так что Арун не сердится на меня).


EDIT: вот @ предложение BlueMagister в:

dt[, 
    Pre_Post_Assignment:= 
    ifelse(
     AdDate < AdDate[OpofInterest], 
     "Pre", 
     ifelse(AdDate == AdDate[OpofInterest], "Per", "Post") 
    ), 
    by=ID 
] 

который я думаю, чище и, скорее всего, быстрее.

+0

спасибо за помощь и совет, я ценю это. Что бы вы предложили сделать, если у вас есть 80 + столбцов, например, в разделе «list (cols ... = ifelse» вашего кода? Именованный вектор имен столбцов? – sgurwin

+0

@sgurwin, я изменил ответ, чтобы решить вашу проблему. См. Материал '.SD'. – BrodieG

+0

Лучше определить новый столбец, чем' cbind' на '.SD', no? –

Смежные вопросы