我无法弄清楚如何在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
的玩家数量,其中两个玩家都参加了焦点游戏,但前提是他们还在另一个游戏中互相对战在同一年的游戏中,此总和应排除正在计算的玩家。
我使用从how to cumulatively add values in one vector in R修改的代码,例如NPg1
:
dtg1 <- dt[,.SD[(g1==1) & (g2==1 | g3==1 | g4==1)][, NPg1:= sum(g1)], by=year]
这会根据我的条件对dt
进行子集并创建总和,但总和包括焦点玩家。例如,NPg1
中的year==2000
对于Tom来说是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))
答案 0 :(得分:2)
一种方法是在year-g1-g2-..-gn
组合上进行笛卡尔联接。
然后在新表上,你可以忽略行&#34;不符合条件的 [见底部注释] - 即玩家对抗自己,以及只玩一场比赛的玩家组合。
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
如果你想保留&#34; 0&#34;计算年度玩家,然后使用
dt.merged[ <filter>, (games) := 0 ]
如果你不关心&#34; 0&#34;计算年度玩家,然后使用
dt.merged <- dt.merged[ ! <filter> ]