1

我很难弄清楚如何在一段时间内对行求和,data.table而在此过程中省略了某个组的值。

假设我有data.table以下形式:

library(data.table)
dt <- data.table(year = c(2000, 2001, 2002, 2003, 2000, 2001, 2002, 2003, 2000, 2001, 2002, 2003, 2000, 2001, 2002, 2003), 
               name = c("Tom", "Tom", "Tom", "Tom", "Fred", "Fred", "Fred", "Fred", "Gill", "Gill", "Gill", "Gill", "Ann", "Ann", "Ann", "Ann"),
               g1 = c(1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
               g2 = c(1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1),
               g3 = c(1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1),
               g4 = c(0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1))

setkey(dt, name, year)

其中g1-g4是玩家name参与的游戏的指标变量year

我想要做的是计算每场比赛的球员人数NPg1-NPg4两名球员都参加了焦点比赛,但前提是他们还在同一年的另一场比赛中相互交手,并且这个总和应该排除球员被谁计算。

我使用从如何在 R 中的一个向量中累积添加值而修改的代码接近,例如NPg1

dtg1 <- dt[,.SD[(g1==1) & (g2==1 | g3==1 | g4==1)][, NPg1:= sum(g1)], by=year]

dt对我的条件进行了子集化并创建了总和,但是,总和包括焦点玩家。例如,对于汤姆来说, NPg1inyear==2000是 1,但它应该是 0,因为即使他参加了比赛,g1他在那一年的另一场比赛中也没有和其他球员比赛。一旦我得到了正确的总和,我就可以为每场比赛做这件事,并将结果合并回一个data.table. 主要问题是,如何在这些条件下获得正确的总和。

结果NPg1应该是这样的

dtg1$NPg1result <- c(0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3)

任何想法将不胜感激。

在@Mike.Gahan 发表评论后:

这是 的子结果g1,也许这在我的帖子中并没有变得很清楚。一旦我正确地做到了这一点,我就可以data.table使用以下方法轻松地将其重新加入:

library(plyr)
dt <- join(dt, dtg1)

或其他合并/加入操作,但由于我的问题主要与子结果有关,我不想打扰其他人。

在@Ricardo Saportas 解决方案之后编辑

所有游戏的完整预期结果如下所示:

dtresult <- data.table(year = c(2000, 2001, 2002, 2003, 2000, 2001, 2002, 2003, 2000, 2001, 2002, 2003, 2000, 2001, 2002, 2003), 
                   name = c("Ann", "Ann", "Ann", "Ann", "Fred", "Fred", "Fred", "Fred", "Gill", "Gill", "Gill", "Gill", "Tom", "Tom", "Tom", "Tom"), 
                   NPg1 = c(0, 1, 3, 3, 0, 0, 3, 3, 0, 0, 3, 3, 0, 1, 3, 3), 
                   NPg2 = c(0, 0, 2, 3, 0, 0, 2, 3, 1, 0, 0, 3, 1, 0, 2, 3), 
                   NPg3 = c(0, 0, 3, 2, 0, 2, 3, 0, 1, 2, 3, 2, 1, 2, 3, 2), 
                   NPg4 = c(0, 0, 2, 2, 0, 1, 0, 0, 0, 1, 2, 2, 0, 0, 2, 2))
4

1 回答 1

2

一种方法是对year-g1-g2-..-gn组合进行笛卡尔连接。

然后在新表上,您可以“忽略行” [见底部注释]不符合条件的玩家 - 即与自己对战的玩家,以及只玩一场游戏的玩家组合。

setkeyv(dt, c("year", games))
dt.merged <- merge(dt, dt, all=TRUE, allow.cartesian=TRUE, suffixes=c("", ".y"))
## ignore players playing against themselves
dt.merged[name != name.y, (games) := 0 ]
## ignore player combinations that only shared one game
dt.merged[ (rowSums(dt.merged[, games, with=FALSE]) <= 1) , (games) := 0 ]
## now just sum itup
results <- dt.merged[, lapply(.SD, sum), keyby=list(year, name), .SDcols=games]
## clean up the names
setnames(results, games, paste0("NP", games))

哪个产量

results

    year name g1 g2 g3 g4
 1: 2000  Ann  0  0  0  0
 2: 2000 Fred  0  0  0  0
 3: 2000 Gill  0  1  1  1
 4: 2000  Tom  1  1  1  0
 5: 2001  Ann  1  1  0  0
 6: 2001 Fred  0  0  1  1
 7: 2001 Gill  0  0  1  1
 8: 2001  Tom  1  0  1  0
 9: 2002  Ann  1  1  1  1
10: 2002 Fred  1  1  1  0
11: 2002 Gill  1  0  1  1
12: 2002  Tom  1  1  1  1
13: 2003  Ann  1  1  1  1
14: 2003 Fred  1  1  0  0
15: 2003 Gill  1  1  1  1
16: 2003  Tom  1  1  1  1

请注意,您有两个选项可以“忽略该行”

如果您想保留年份玩家的“0”计数,请使用

dt.merged[ <filter>,  (games) := 0 ]

如果您不关心年份玩家的“0”计数,请使用

dt.merged <- dt.merged[ ! <filter> ]
于 2014-08-27T02:06:17.457 回答