Взяв среднее значение столбца над списком фреймов данных в R
Вот что я пытаюсь сделать. У моего фрейма данных есть фактор-переменная "страна", и я хочу разделить фрейм данных по стране. Затем я хочу взять среднее значение столбца по каждой переменной для фрейма данных каждой страны.
Данные здесь: https://github.com/pourque/country-data
Я сделал это до сих пор...
myList <- split(df1, df1$country)
for(i in 1:length(myList)) {
aggregate <- mapply(myList[[i]][,-c(38:39)], colMeans)
}
(Я не включаю 38-й и 39-й столбцы, потому что это факторы.)
Я прочитал это ( функция более чем в одном списке), что заставляет меня думать, что mapply является ответом здесь... но я получаю эту ошибку:
Error in match.fun(FUN) :
'myList[[i]][, -c(38:39)]' is not a function, character or symbol
Может я неправильно форматирую?
4 ответа
Ответ data.table:
library(data.table)
setDT(df1)[, lapply(.SD, mean), by = country, .SDcols = -c('age', 'gender')]
Теперь более аккуратный синтаксис с отменой выбора в.SDcols благодаря пользователю Arun
Чтобы объяснить, что здесь происходит:
setDT(df1)
сделать data.frame data.tablelapply(.SD, mean)
для каждого столбца в подмножестве данных возьмитеmean
by = county
сделать это по группам в соответствии сcountry
.SDcols = -c('age', 'gender')
пропускатьage
а такжеgender
столбцы из подмножества данных
Это просто в базе R, используя aggregate
без необходимости split
data.frame в список заранее. Вот пример использования встроенных данных радужной оболочки, где вы вычисляете mean
всех переменных, кроме тех, которые в первом и втором столбце по группам Species
:
data(iris)
aggregate(. ~ Species, iris[-(1:2)], mean)
# Species Petal.Length Petal.Width
#1 setosa 1.462 0.246
#2 versicolor 4.260 1.326
#3 virginica 5.552 2.026
.
внутри aggregate
используется, чтобы указать, что вы хотите использовать все оставшиеся столбцы data.frame, кроме переменной группировки (в данном случае - Species). И потому что вы указываете iris[-(1:2)]
в качестве входных данных первый и второй столбцы также не используются.
Для ваших данных это должно быть что-то вроде:
aggregate(. ~ country, df1[-c(38:39)], mean)
library(dplyr)
df1 %>%
group_by(country) %>%
select(-age, -gender) %>%
summarise_each(funs(mean))
Если вы настаиваете на сохранении всего в списке:
#split and make list of df
myList <- split(df, df$country)
#aggregate without age and gender
my_aggregate <- function(df_inlist) {
df_inlist <- aggregate(.~country, df_inlist[ , -c(38, 39)], mean)
}
#Apply aggregate function on all data frames in the list
out <- lapply(myList, function (x) {
my_aggregate(x)
})
out
это list
data.frames для каждой страны и colmeans по переменным. Как собрать все это вместе в data.frame:
composite_df <- do.call(rbind, out)