R-为嵌套for循环中的数据帧子集赋值

R-为嵌套for循环中的数据帧子集赋值,r,for-loop,dataframe,subset,nested-loops,R,For Loop,Dataframe,Subset,Nested Loops,R版本3.3.2 我试图根据数据帧中其他变量的值,使用嵌套for循环将某些值分配给数据帧中的空变量。然而,输出不是我所期望的 以下是一个可复制的示例: id <- c("ID61", "ID61", "ID63", "ID69", "ID69", "ID69", "ID69", "ID69", "ID80", "ID80", "ID80", "ID81", "ID81", "ID81", "ID81") Round <- c(1, 2, 1, 1, 2, 3, 4, 5, 1, 2,

R版本3.3.2

我试图根据数据帧中其他变量的值,使用嵌套for循环将某些值分配给数据帧中的空变量。然而,输出不是我所期望的

以下是一个可复制的示例:

id <- c("ID61", "ID61", "ID63", "ID69", "ID69", "ID69", "ID69", "ID69", "ID80", "ID80", "ID80", "ID81", "ID81", "ID81", "ID81")
Round <- c(1, 2, 1, 1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 3, 4)
nrPosRound <- c(2, 0, 2, 15, 8, 4, 4, 0, 3, 1, 1, 0, 0, 0, 0)
Y <- rep(NA, 15)
df <- data.frame(id, Round, nrPosRound, Y)
我希望它看起来像这样,在嵌套for循环之后:

> df
     id Round nrPosRound Y
1  ID61     1          2 FP
2  ID61     2          0 FP
3  ID63     1          2 FP
4  ID69     1         15 FP
5  ID69     2          8 FP
6  ID69     3          4 FP
7  ID69     4          4 FP
8  ID69     5          0 FP
9  ID80     1          3 1
10 ID80     2          1 1
11 ID80     3          1 1
12 ID81     1          0 0
13 ID81     2          0 0
14 ID81     3          0 0
15 ID81     4          0 0
for (i in 1:nrow(df)) {

  current_id <- df$id[i]
  id_group <- df[df$id == curr_id, ]

  for (j in 1:nrow(id_group)) {

    current_Round <- id_group$Round[j] 
    remainder_Rounds <- id_group$Round[(j+1):nrow(id_group)]

    current_nrPos <- id_group$nrPosRound[id_group$Round == current_Round]
    remainder_nrPos <- id_group$nrPosRound[id_group$Round %in% remainder_Rounds]

    ifelse(curr_nrPos >= 3 & remainder_nrPos >= 1,
           df$Y[i] <- 1, ifelse(curr_nrPos == 0 & remainder_nrPos == 0,
                                        df$Y[i] <- 0, "FP"))
  }
}
我想要的是将值“1”赋给变量“Y”,如果对于同一个“id”,在某个“轮”中有3个或更多的正值(nrPosRound>=3),并且在接下来的轮中至少有1个正值(nrPosRound>=1)。 如果在同一“id”的每个“轮”中,“nrPosRound”为“0”,则将为“Y”分配值“0”。 如果不满足之前的条件,则应将“Y”指定为“FP”(假阳性)。
如果该“id”只有1个“Round”,则如果“nrPosRound”大于等于3,则“Y”的值为“1”;如果“nrPosRound”==0,则值为“0”;如果“nrPosRound”为值“FP”,则可以使用
dplyr
完成此操作。在下面的代码中,我首先
group\u by
id

我从上次的_创建了一个中间变量min_,以查看在每一轮之后是否有一个零。为此,我首先使用
arrange(desc(Round))
从最后一个重新排序。 之后,我使用
cummin
获得累计最小值

然后,我对数据重新排序并执行三次
ifelse
,以获得所需的结果。顺便说一句,你可能不需要第二个ifelse,因为它会被第一个ifelse捕获,但我在你的问题中包含了它

id <- c("ID61", "ID61", "ID63", "ID69", "ID69", "ID69", "ID69", "ID69", "ID80", "ID80", "ID80", "ID81", "ID81", "ID81", "ID81")
Round <- c(1, 2, 1, 1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 3, 4)
nrPosRound <- c(2, 0, 2, 15, 8, 4, 4, 0, 3, 1, 1, 0, 0, 0, 0)
df1 <- data.frame(id, Round, nrPosRound,stringsAsFactors=FALSE)

library(dplyr)
df1 %>%
group_by(id) %>%
arrange(desc(Round)) %>%
mutate(min_from_last=cummin(nrPosRound)) %>%
arrange(Round)  %>%
mutate(Y= ifelse(max(nrPosRound)>=3 & min_from_last>0 ,"1",
           ifelse(n()==1 & nrPosRound>=3,"1",
           ifelse(max(nrPosRound)==0,"0","FP"))))

      id Round nrPosRound min_from_last     Y
   (chr) (dbl)      (dbl)         (dbl) (chr)
1   ID61     1          2             0    FP
2   ID61     2          0             0    FP
3   ID63     1          2             2    FP
4   ID69     1         15             0    FP
5   ID69     2          8             0    FP
6   ID69     3          4             0    FP
7   ID69     4          4             0    FP
8   ID69     5          0             0    FP
9   ID80     1          3             1     1
10  ID80     2          1             1     1
11  ID80     3          1             1     1
12  ID81     1          0             0     0
13  ID81     2          0             0     0
14  ID81     3          0             0     0
15  ID81     4          0             0     0
id%
排列(圆形)%>%
变异(Y=ifelse(max(nrPosRound)>=3&min\u从最后一个>0,“1”,
如果else(n()==1&nrPosRound>=3,“1”,
ifelse(最大(nrPosRound)=0,“0”,“FP”))
从上一个Y开始,id为nrPosRound min_
(chr)(dbl)(dbl)(dbl)(chr)
1 ID61 12 0 FP
2 ID61 2 0 0 FP
3 ID63 1 2 FP
4 ID69 1150 FP
5 ID69 2 8 0 FP
6 ID69 3 4 0 FP
7 ID69 4 0 FP
8 ID69 5 0 FP
9 ID80 1 3 1 1
10 ID80 2 1 1
11 ID80 3 1 1
12 ID81 1 0 0 0
13 ID81 2 0 0 0 0
14 ID81 3 0 0 0 0
15 ID81 4 0 0 0

这是一个基本的R解决方案

id.vals <- unique(df$id)

for (i in 1:length(id.vals)) {
    group.ind <- df$id == id.vals[i]
    id_group  <- df[group.ind, 'nrPosRound']
    n   <- length(id_group)
    Y   <- rep(NA, n)
    g3  <- any(id_group >= 3)
    a0  <- all(id_group == 0)
    for (j in 1:n) {
        if (g3 & all(id_group[j:n] >= 1)) Y[j] <- 1
        else if (a0) Y[j] <- 0
        else Y[j] <- 'FP'
    }
    df$Y[group.ind] <- Y
}

id.vals非常感谢您!这是一个优雅的解决方案,我显然把过程复杂化了。最后我加了一句:
arrange(id,Round)
非常感谢您的解决方案,Ryan!这就是我想要实现的嵌套for循环逻辑。它的工作原理和我想要的完全一样!
id.vals <- unique(df$id)

for (i in 1:length(id.vals)) {
    group.ind <- df$id == id.vals[i]
    id_group  <- df[group.ind, 'nrPosRound']
    n   <- length(id_group)
    Y   <- rep(NA, n)
    g3  <- any(id_group >= 3)
    a0  <- all(id_group == 0)
    for (j in 1:n) {
        if (g3 & all(id_group[j:n] >= 1)) Y[j] <- 1
        else if (a0) Y[j] <- 0
        else Y[j] <- 'FP'
    }
    df$Y[group.ind] <- Y
}