Средневзвешенное значение для нескольких столбцов по группам (в таблице данных).
Этот вопрос следует за другим вопросом о средневзвешенных значениях группы: я хотел бы создать взвешенные средние значения внутри группы, используя data.table
, Разница с первоначальным вопросом заключается в том, что имена переменных, которые должны быть усреднены, указываются в строковом векторе.
Данные:
df <- read.table(text= "
region state county weights y1980 y1990 y2000
1 1 1 10 100 200 50
1 1 2 5 50 100 200
1 1 3 120 1000 500 250
1 1 4 2 25 100 400
1 1 4 15 125 150 200
2 2 1 1 10 50 150
2 2 2 10 10 10 200
2 2 2 40 40 100 30
2 2 3 20 100 100 10
", header=TRUE, na.strings=NA)
Используя предложенный Роландом ответ на вышеупомянутый вопрос:
library(data.table)
dt <- as.data.table(df)
dt2 <- dt[,lapply(.SD,weighted.mean,w=weights),by=list(region,state,county)]
У меня есть вектор со строками для динамического определения столбцов, для которых требуется средневзвешенное значение внутри группы.
colsToKeep = c("y1980","y1990")
Но я не знаю, как передать его в качестве аргумента для магии data.table.
Я старался
dt[,lapply(
as.list(colsToKeep),weighted.mean,w=weights),
by=list(region,state,county)]`
но тогда я получаю:
Error in x * w : non-numeric argument to binary operator
Не уверен, как добиться того, чего я хочу.
Дополнительный вопрос: я бы хотел, чтобы вместо имен V1 и V2 были сохранены оригинальные имена столбцов.
Примечание: я использую версию 1.9.3 пакета data.table.
2 ответа
Обычно вы должны уметь:
dt2 <- dt[,lapply(.SD,weighted.mean,w=weights),
by = list(region,state,county), .SDcols = colsToKeep]
т.е. просто предоставляя только эти столбцы .SDcols
, Но на данный момент это не сработает из-за ошибки, в этом weights
столбец не будет доступен, потому что он не указан в .SDcols
,
Пока это не исправлено, мы можем сделать это следующим образом:
dt2 <- dt[, lapply(mget(colsToKeep), weighted.mean, w = weights),
by = list(region, state, county)]
# region state county y1980 y1990
# 1: 1 1 1 100.0000 200.0000
# 2: 1 1 2 50.0000 100.0000
# 3: 1 1 3 1000.0000 500.0000
# 4: 1 1 4 113.2353 144.1176
# 5: 2 2 1 10.0000 50.0000
# 6: 2 2 2 34.0000 82.0000
# 7: 2 2 3 100.0000 100.0000
Я не знаю data.table
но вы рассматривали возможность использования dplyr
? Я думаю, что это почти так же быстро, как data.table
library(dplyr)
df %>%
group_by(region, state, county) %>%
summarise(mean_80 = weighted.mean(y1980, weights),
mean_90 = weighted.mean(y1990, weights))
Source: local data frame [7 x 5]
Groups: region, state
region state county mean_80 mean_90
1 1 1 1 100.0000 200.0000
2 1 1 2 50.0000 100.0000
3 1 1 3 1000.0000 500.0000
4 1 1 4 113.2353 144.1176
5 2 2 1 10.0000 50.0000
6 2 2 2 34.0000 82.0000
7 2 2 3 100.0000 100.0000