R цикл до нового взвешенного фрейма данных - PullRequest
1 голос
/ 02 июня 2019

У меня есть высокий фрейм данных как таковой:

data = data.frame("id"=c(1,2,3,4,5,6,7,8,9,10),
                  "group"=c(1,1,2,1,2,2,2,2,1,2),
                  "type"=c(1,1,2,3,2,2,3,3,3,1),
                  "score1"=c(sample(1:4,10,r=T)),
                  "score2"=c(sample(1:4,10,r=T)),
                  "score3"=c(sample(1:4,10,r=T)),
                  "score4"=c(sample(1:4,10,r=T)),
                  "score5"=c(sample(1:4,10,r=T)),
                  "weight1"=c(173,109,136,189,186,146,173,102,178,174),
                  "weight2"=c(147,187,125,126,120,165,142,129,144,197),
                  "weight3"=c(103,192,102,159,128,179,195,193,135,145),
                  "weight4"=c(114,182,199,101,111,116,198,123,119,181),
                  "weight5"=c(159,125,104,171,166,154,197,124,180,154))

library(reshape2)
library(plyr)

data1 <- reshape(data, direction = "long",
                 varying = list(c(paste0("score",1:5)),c(paste0("weight",1:5))),
                 v.names = c("score","weight"),
                 idvar = "id", timevar = "count", times = c(1:5))
data1 <- data1[order(data1$id), ]

И то, что я хочу создать, - это новый фрейм данных:

want = data.frame("score"=rep(1:4,6),
                  "group"=rep(1:2,12),
                  "type"=rep(1:3,8),
                  "weightedCOUNT"=NA) # how to calculate this? count(data1, score, wt = weight)

Я просто не уверен, как рассчитать weightedCOUNT, который должен применять весовые коэффициенты к переменной Score, поэтому он дает в столбце weightedCOUNT взвешенное значение, которое агрегируется по баллам, группам и типам.

Ответы [ 2 ]

1 голос
/ 02 июня 2019

Опция может быть melt (из data.table - которая может принимать несколько measure patterns, а затем группироваться по 'group', 'type' получить count

library(data.table)
library(dplyr)
melt(setDT(data), measure = patterns('^score', "^weight"), 
   value.name = c("score", "weight")) %>% 
   group_by(group, type) %>%
   count(score, wt = weight)

Если нам нужен complete набор комбинаций

library(tidyr)
melt(setDT(data), measure = patterns('^score', "^weight"), 
       value.name = c("score", "weight")) %>%      
   group_by(group, type) %>%
   ungroup %>% 
   complete(group, type, score, fill = list(n = 0))
0 голосов
/ 02 июня 2019

Если я правильно понимаю, weightedCOUNT - это сумма весов, сгруппированных по score, group и type.

. Для полноты картины я хотел бы показать, как принятое решение будет выглядеть, если оно реализовано в чистом базовом R и чистом data.table синтаксисе, соответственно

базовый R

ОП уже почти готов.Он уже изменил data из широкого формата в длинный для переменных с несколькими значениями.Отсутствовал только последний шаг агрегации:

data1 <- reshape(data, direction = "long",
                 varying = list(c(paste0("score",1:5)),c(paste0("weight",1:5))),
                 v.names = c("score","weight"),
                 idvar = "id", timevar = "count", times = c(1:5))

result <- aggregate(weight ~ score + group + type, data1, FUN = sum)

result
   score group type weight
1      1     1    1    479
2      3     1    1    558
3      4     1    1    454
4      1     2    1    378
5      2     2    1    154
6      3     2    1    174
7      4     2    1    145
8      1     2    2    535
9      2     2    2    855
10     3     2    2    248
11     4     2    2    499
12     1     1    3    189
13     2     1    3    351
14     3     1    3    600
15     4     1    3    362
16     1     2    3    596
17     2     2    3    265
18     3     2    3    193
19     4     2    3    522

result можно переупорядочить по

with(result, result[order(score, group, type), ])
   score group type weight
1      1     1    1    479
12     1     1    3    189
4      1     2    1    378
8      1     2    2    535
16     1     2    3    596
13     2     1    3    351
5      2     2    1    154
9      2     2    2    855
17     2     2    3    265
2      3     1    1    558
14     3     1    3    600
6      3     2    1    174
10     3     2    2    248
18     3     2    3    193
3      4     1    1    454
15     4     1    3    362
7      4     2    1    145
11     4     2    2    499
19     4     2    3    522

data.table

Как показано akrun , melt() из пакета data.table можно комбинировать с dplyr.В качестве альтернативы мы можем использовать синтаксис data.table для агрегации:

library(data.table)
cols <- c("score", "weight") # to save typing
melt(setDT(data), measure = patterns(cols), value.name = cols)[
  , .(weightedCOUNT = sum(weight)), keyby = .(score, group, type)]
    score group type weightedCOUNT
 1:     1     1    1           479
 2:     1     1    3           189
 3:     1     2    1           378
 4:     1     2    2           535
 5:     1     2    3           596
 6:     2     1    3           351
 7:     2     2    1           154
 8:     2     2    2           855
 9:     2     2    3           265
10:     3     1    1           558
11:     3     1    3           600
12:     3     2    1           174
13:     3     2    2           248
14:     3     2    3           193
15:     4     1    1           454
16:     4     1    3           362
17:     4     2    1           145
18:     4     2    2           499
19:     4     2    3           522

Параметр keyby используется для группировки и упорядочения выходных данных за один шаг.

Заполнение пропущенных комбинаций группирующих переменных также возможно в синтаксисе data.table с использованием функции cross join CJ():

melt(setDT(data), measure = patterns(cols), value.name = cols)[
  , .(weightedCOUNT = sum(weight)), keyby = .(score, group, type)][
    CJ(score, group, type, unique = TRUE), on = .(score, group, type)][
      is.na(weightedCOUNT), weightedCOUNT := 0][]
    score group type weightedCOUNT
 1:     1     1    1           479
 2:     1     1    2             0
 3:     1     1    3           189
 4:     1     2    1           378
 5:     1     2    2           535
 6:     1     2    3           596
 7:     2     1    1             0
 8:     2     1    2             0
 9:     2     1    3           351
10:     2     2    1           154
11:     2     2    2           855
12:     2     2    3           265
13:     3     1    1           558
14:     3     1    2             0
15:     3     1    3           600
16:     3     2    1           174
17:     3     2    2           248
18:     3     2    3           193
19:     4     1    1           454
20:     4     1    2             0
21:     4     1    3           362
22:     4     2    1           145
23:     4     2    2           499
24:     4     2    3           522
    score group type weightedCOUNT
...