Подтвердить что ты не робот

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

Хорошо, второй вопрос 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. Я использовал, чтобы написать цикл в оболочке, чтобы сгенерировать этот код, но это не то, как программисты решают проблемы, не так ли?

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

4b9b3361

Ответ 1

Вы можете использовать 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). В этом примере это больше нажатий клавиш, но дает вам огромную гибкость:

Библиотека (reshape2)

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

Ответ 2

Вы даже можете упростить второй подход, предложенный Андри, полностью опустив вызов 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