在 R 中有条件地用另一列(但不在同一行)的值填充一列的值

fill values of a column with values from another column (but not on the same row), conditionally, in R

我有一个问题,关于如何有条件地用另一列(但不在同一行)的值填充一列的值。 让我用我的数据集的例子来解释这种情况。 这是我的数据集,其中两个个体 (ID) 列正在进行二元战斗(fight_id 列)。对于每场战斗,我都有两条线(每个人一条)。我想要做的是在每一行的 "opponent" 列中填写同一战斗 ID 中另一个人的 ID。所以我想生成粗体数据。

ID FIGHT_ID V3 OPP
12 -- 1 ------ 1 -- 13
13 -- 1 ------ 0 -- 12
14 -- 2 ------ 0 -- 15
15 -- 2 ------ 1 -- 14

我要写对手的名字(填写OPP栏),意思是复制OPP栏中参与同一场战斗的其他人的ID。我基本上是在转换个人成为彼此的对手。 我想在同一个战斗 ID 中分配一个 1 或 0 的列,然后在所有数据集的战斗 ID 中进行循环,以执行类似的操作 :“如果 v3 = 1,则复制 v3 = 0 处的 ID 值,如果 v3 = 0,则复制 v3 = 1 处的 ID 值”。 这个概念很简单,但我似乎无法弄清楚(如果它们在同一行我可以,但在这里我们必须在另一行中寻找一个值)。 在 R 语言中,我想这样做:

for(我在1:nrow(数据)){ for (j in 1:length(levels(data$Fight_ID))) { data$OPP[i] <- if(data$v3[i]==1) data$ID[i] else if (data$v3[i]==0) 数据$ID[i] }

除了粗体部分,我想写 data$ID[i] 的值,但 where v3 == 0 ,反之亦然第二个粗体部分。 如果它存在,它将类似于 "data$ID[i] where data$v3[i]==0" .

显然还有其他方法可以做到这一点,但根据我所掌握的 R 知识,这对我来说似乎是合乎逻辑的。 谢谢您的帮助! 弗朗西斯卡

使用 plyr,假设每个 id 只有 2 行:

df = data.frame(id=12:15, fight_id=c(1,1,2,2), v3=c(1,0,0,1))
#  id fight_id v3
#1 12        1  1
#2 13        1  0
#3 14        2  0
#4 15        2  1

library(plyr)
ldply(split(df, df$fight_id), function(u) transform(u, opp=rev(u$id)))

#  .id id fight_id v3 opp
#1   1 12        1  1  13
#2   1 13        1  0  12
#3   2 14        2  0  15
#4   2 15        2  1  14

或基数 R:

do.call(rbind, lapply(split(df, df$fight_id), function(u) transform(u, opp=rev(u$id))))

#    id fight_id v3 opp
#1.1 12        1  1  13
#1.2 13        1  0  12
#2.3 14        2  0  15
#2.4 15        2  1  14

data.table:

library(data.table)
rbindlist(lapply(split(df, df$fight_id), function(u) transform(u, opp=rev(u$id))))

#   id fight_id v3 opp
#1: 12        1  1  13
#2: 13        1  0  12
#3: 14        2  0  15
#4: 15        2  1  14

还是data.table:

library(data.table)
setDT(df)[,opp:=rev(id), by=fight_id]

#> df
#   id fight_id v3 opp
#1: 12        1  1  13
#2: 13        1  0  12
#3: 14        2  0  15
#4: 15        2  1  14

还有一个非常有趣的没有循环的基础 R :)

df     = df[order(df$id),]
df$opp = df$id[rep(seq(0,length(df)/2,2), each=2)+2:1]

#> df
#  id fight_id v3 opp
#1 12        1  1  13
#2 13        1  0  12
#3 14        2  0  15
#4 15        2  1  14