генерирование сумм данных в соответствии со значениями переменной

У меня есть данные, похожие на это:

Hosp    Score   Var1    Var2    Var3
1       0       5       3       0
1       1       10      8       1
1       2       11      8       2
1       3       5       3       2
2       0       6       4       0
2       2       10      6       1
2       3       10      7       2
3       1       4       3       2
etc...

Есть приблизительно 800 Хопсов и 4 уровня коэффициента (0,1,2,3). Некоторые хосты не имеют наблюдения за определенным уровнем очков

Я хотел бы создать новый фрейм данных, в котором переменные Var1, Var2 и Var3 суммируются. Таким образом, используя данные выше, это даст

Hosp    Var1    Var2    Var3
1       32      22      5
2       26      17      3
3       4       3       2

Это было бы тривиально в SQL (и я думаю, что и в R тоже!), Но единственный способ, который я нашел до сих пор, - это цикл, который добавляет новую строку каждый раз, когда изменяется Hosp, и увеличивает переменные, когда это не так.изменить (конечно, данные отсортированы в Hosp).

Есть ли отличный способ сделать это?

Ответы на вопрос(3)

Опираясь нарешение от mrdwab, но с более коротким синтаксисом:

aggregate(temp[3:5], temp[1], sum)

При этом используется тот факт, что фрейм данных является списком, и поэтому подмножество в одну скобку будет создавать фрейм данных с подмножеством столбцов. Это позволяет избежать всегоlist звонки.

Еще одна альтернатива:

library(plyr)
ddply(temp[-2], .(Hosp), colSums, na.rm = TRUE)

Это разбивает фрейм данных на куски поHospи вычисляет суммы столбцов для каждого такого блокаcolSums(chunk, na.rm = TRUE) сделал бы это.[-2] опускаетScore столбец из ввода, так что вы выигралине получить сумму за это.

Увы, как правильно указал mrdwab в комментарии ниже, приведенное выше также суммируетHosp колонка. Моим первым решением этой проблемы было следующее:

ddply(t[-2], .(Hosp), function(d){colSums(d[-1], na.rm = TRUE)})

Это уронитHosp столбец с аргументом вcolSumsтак, чтобы это непереопределить исходный столбец с таким именем,ddply по умолчанию. В целом, это уже не симпатичное и не быстрое решение. Но так как у него есть функция, работающая с чётко прописанными кусками, она очень гибкая, поэтому яоставлю это для справки.

В еще одном комментарии mrdwab предложил лучшее решение:

ddply(temp[-2], .(Hosp), numcolwise(sum))

Это работает, потому чтоnumcolwise, который основан наcolwiseвнутренне звонитstrip_splits который, в свою очередь, удаляет те столбцы, которые использовались для выполнения разделения, т.е.Hosp в этом случае. Все функции в предыдущем предложении взяты из.plyr

 MvG12 окт. 2012 г., 13:55
@ mrdwab, спасибо, что поймали это.
 A5C1D2H2I1M1N2O1R2T112 окт. 2012 г., 13:47
Осторожнее, как тымы сделали это,plyr Альтернатива также суммируетHosp» колонка!
 A5C1D2H2I1M1N2O1R2T112 окт. 2012 г., 14:31
Отредактируйте свой ответ, чтобы прочитать следующее, и выполучил +1 за то, что заставил меня провести какое-то исследование (ям вообще больше из базового R парня)ddply(temp[-2], .(Hosp), numcolwise(sum))
Решение Вопроса

использованиеaggregate(), Предполагая вашdata.frame назван "темп», используйте:

aggregate(list(Var1 = temp$Var1, Var2 = temp$Var2, Var3 = temp$Var3), 
          list(Hosp = temp$Hosp), sum)
#   Hosp Var1 Var2 Var3
# 1    1   31   22    5
# 2    2   26   17    3
# 3    3    4    3    2

Дляslick Для этого воспользуйтесь формулой нотации для:aggregate()

aggregate(cbind(Var1, Var2, Var3) ~ Hosp, temp, sum)

Обратите внимание, однако, что есть разница в том, какNA значения обрабатываются по умолчаниюdata.frame метод иformula метод.

Обновить

Вы упомянули в исходном вопросе с использованием SQL. Я нене имеет большого опыта работы с SQL, но есть иsqldf пакет, с помощью которого вы можете сделать следующее:

sqldf("select Hosp, 
      sum(Var1) `Var1`, sum(Var2) `Var2`, sum(Var3) `Var3` 
      from temp 
      group by Hosp")
#   Hosp Var1 Var2 Var3
# 1    1   31   22    5
# 2    2   26   17    3
# 3    3    4    3    2
 Robert Long12 окт. 2012 г., 13:04
Блестящий! ..... +1
 A5C1D2H2I1M1N2O1R2T112 окт. 2012 г., 13:45
@longrob, также проверьте "применять" семейство функций для других типов агрегации, которые могут быть полезны для этого типа работы. "Доби» Пакет также полезен.

data.table решение для памяти, кодирования и эффективности времени.

Учитывая, что вы привыкли использоватьSQL Вы должны найти синтаксис дляdata.table просто, как только вы посмотрели на виньетки для.data.table

# assuming your data is in DF
library(data.table)
DT <- data.table(DF)

DT[, lapply(.SD, sum), by = hosp, .SDcols = c('Var1', 'Var2', 'Var3')]

В этом случае вы можете использовать короткую рукуlapply(.SD, FUN), настройка.SDcols быть переменными для запускаlapply на.

Более многословный, ноSQLподобный подход для получения одинаковых результатов будет

DT[, list(Var1 = sum(Var1), Var2 =sum(Var2), Var3 = sum(Var3)), by = hosp]

но зачем писать весь этот дополнительный код, еслиТ надо!

Ваш ответ на вопрос