2014-09-24 3 views
6

Этот вопрос следует за другим на group weighted means: Я хотел бы создать взвешенные внутригрупповые средние значения, используя 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 magic.

Я попытался

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.

NB Я использую версию 1.9.3 пакета данных.table.

ответ

8

Как правило, вы должны быть в состоянии сделать:

dt2 <- dt[,lapply(.SD,weighted.mean,w=weights), 
      by = list(region,state,county), .SDcols = colsToKeep] 

т.е. просто путем предоставления только те столбцы .SDcols. Но на данный момент это не сработает due to a bug, поскольку колонка 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 
+0

Ошибка все еще присутствует или первый подход больше не рекомендуется? 16 декабря 2015 года я получаю следующее: '' Ошибка в as.double (w): не может принуждать тип 'замыкание' к вектору типа 'double''' – PatrickT

+1

ошибка еще не исправлена, извините :-(. может делать: 'dt [, lapply (mget (colsToKeep), weighted.mean, w = weight), by =. (region, state, country)]. Ваша ошибка, похоже, указывает на то, что вы используете' as.double' с функцией как входной (которая не связана). – Arun

+0

спасибо. По существу, ваше предложение состоит в том, чтобы использовать '' mget() '', а не '' as.list (.SD) [] '' правильно?(Я знаю, что точка, которую вы используете после '' by = '', является сокращением для '' list'', так что бит кода совпадает с вашим обходным решением выше) (О сообщении об ошибке, я думаю, что просто копирую -pasted данные OP, но не прошел через data.frame.) – PatrickT

0

Я не знаю 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 
+0

Спасибо за вашу помощь, но мне нужно использовать data.table, а также ваш ответ не рассматривает новое ограничение на мой вопрос, который что столбцы должны динамически определяться вектором. – Peutch

+0

Неплохо, я должен был внимательно прочитать ваш пост. Если вы решите переключиться на dplyr, [здесь] (http://stackoverflow.com/questions/26003574/r-dplyr-mutate-use-dynamic-variable-names) пример, который может быть полезен – kferris10

Смежные вопросы