ddply +summary для повторения одной и той же статистической функции в большом количестве столбцов

Хорошо, второй вопрос R в быстрой последовательности.

Мои данные:

           Timestamp    St_01  St_02 ...
1 2008-02-08 00:00:00  26.020 25.840 ...
2 2008-02-08 00:10:00  25.985 25.790 ...
3 2008-02-08 00:20:00  25.930 25.765 ...
4 2008-02-08 00:30:00  25.925 25.730 ...
5 2008-02-08 00:40:00  25.975 25.695 ...
...

Обычно я бы использовал комбинацию ddply и summarize для расчета ансамблей (например, среднее значение за каждый час в течение всего года).

В приведенном выше случае я бы создал категорию, например. час (например, strptime(data$Timestamp,"%H") -> data$hour, а затем используйте эту категорию в ddply, например ddply(data,"hour", summarize, St_01=mean(St_01), St_02=mean(St_02)...), для усреднения по категориям в каждом из столбцов.

но вот где это становится липким. У меня более 40 столбцов, и я не готов вводить их все один за другим в качестве параметров функции summarize. Раньше я писал цикл в оболочке для генерации этого кода, но это не то, как программисты решают проблемы, не так ли?

Итак, скажите, пожалуйста, есть ли у кого-нибудь лучший способ добиться того же результата, но с меньшим количеством нажатий клавиш?


person Reuben L.    schedule 28.05.2012    source источник
comment
Или измените форму переменных St, а затем используйте свои любимые функции агрегирования by, aggregate, ddply для объединения с помощью c(hour,index), где index — это переменная, созданная при изменении формы.   -  person Ari B. Friedman    schedule 28.05.2012
comment
легкие моменты для тебя :-)   -  person    schedule 24.04.2015
comment
лол спасибо! хахаха. Вера в человечество восстановлена.   -  person Reuben L.    schedule 24.04.2015


Ответы (2)


Вы можете использовать numcolwise() для запуска сводки по всем числовым столбцам.

Вот пример использования iris:

ddply(iris, .(Species), numcolwise(mean))
     Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1     setosa        5.006       3.428        1.462       0.246
2 versicolor        5.936       2.770        4.260       1.326
3  virginica        6.588       2.974        5.552       2.026

Точно так же есть catcolwise() для суммирования по всем категориальным столбцам.

См. ?numcolwise для получения дополнительной справки и примеров.


ИЗМЕНИТЬ

Альтернативный подход — использовать reshape2 (предложен @gsk3). В этом примере больше нажатий клавиш, но вы получаете огромную гибкость:

библиотека (изменить форму2)

miris <- melt(iris, id.vars="Species")
x <- ddply(miris, .(Species, variable), summarize, mean=mean(value))

dcast(x, Species~variable, value.var="mean")
     Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1     setosa        5.006       3.428        1.462       0.246
2 versicolor        5.936       2.770        4.260       1.326
3  virginica        6.588       2.974        5.552       2.026
person Andrie    schedule 28.05.2012
comment
одна вещь. как это работает с подведением итогов? потому что мне нужно подвести итог категорически в каждом столбце тоже. - person Reuben L.; 28.05.2012
comment
Я не уверен, что ты имеешь в виду. Использование colwise или семьи обычно означает, что вам не нужно использовать summarize. Не могли бы вы расширить свой вопрос? - person Andrie; 28.05.2012
comment
@R-L, это или-или, два разных подхода. Оба имеют свои достоинства. Вариант melt удобен, если вы собираетесь выполнять большое количество статистических расчетов по каждому столбцу и хотите просмотреть промежуточные результаты. - person smci; 01.04.2014

Вы даже можете упростить второй подход, предложенный Andrie, полностью исключив вызов ddply. Просто укажите mean в качестве функции агрегации в вызове dcast:

library(reshape2)
miris <- melt(iris, id.vars="Species")
dcast(miris, Species ~ variable, mean)

     Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1     setosa        5.006       3.428        1.462       0.246
2 versicolor        5.936       2.770        4.260       1.326
3  virginica        6.588       2.974        5.552       2.026

Тот же результат можно очень быстро вычислить с помощью пакета data.table. Переменная .SD в выражении j — это специальная переменная data.table, содержащая подмножество данных для каждой группы, за исключением всех столбцов, используемых в by.

library(data.table)
dt_iris <- as.data.table(iris)
dt_iris[, lapply(.SD, mean), by = Species]

     Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1:     setosa        5.006       3.428        1.462       0.246
2: versicolor        5.936       2.770        4.260       1.326
3:  virginica        6.588       2.974        5.552       2.026

Еще одним вариантом может быть новая версия 0.2 пакета Hadley dplyr.

library(dplyr)
group_by(iris, Species) %>% summarise_each(funs(mean))

Source: local data frame [3 x 5]

     Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1     setosa        5.006       3.428        1.462       0.246
2 versicolor        5.936       2.770        4.260       1.326
3  virginica        6.588       2.974        5.552       2.026
person alex23lemm    schedule 25.04.2014