在具有多个条件的组中标记行

时间:2018-09-06 17:01:47

标签: r if-statement grouping

我在这里和其他地方都看过,但是找不到能够完全使用R来完成的工作。

我有类似以下的数据,其中col1是唯一ID,col2是组ID变量,col3是状态码。我需要标记所有具有相同组ID的行,并且其中任何行都有特定的状态码,在这种情况下,X为== 1,否则为0。

ID   GroupID    Status   Flag
 1    100        A        1
 2    100        X        1
 3    102        A        0
 4    102        B        0
 5    103        B        1 
 6    103        X        1
 7    104        X        1
 8    104        X        1
 9    105        A        0
 10   105        C        0

我尝试写一些ifelse,其中groupID == groupID和status == X然后1 else 0,但这是行不通的。状态模式是随机的。在此示例中,GroupID仅是成对的,但是我不想假设在代码b / c中,我还有另一个实例,其中GroupID中有3行或更多行。

如果这是开放式IE,这将是有帮助的,如有必要,我可以添加其他条件,例如,对于每个匹配的组ID,状态== X,其他或其他等等。

谢谢!

5 个答案:

答案 0 :(得分:3)

使用 dplyr 软件包很容易进行此类基于组的操作。

数据:

library(dplyr)

txt <- 'ID   GroupID    Status
1    100        A        
2    100        X        
3    102        A        
4    102        B        
5    103        B         
6    103        X        
7    104        X        
8    104        X        
9    105        A        
10   105        C        '

df <- read.table(text = txt, header = T)

一旦有了数据框,就可以使用group_by函数建立dplyr组。然后,每个组将应用mutate命令,为每行创建一个新的列条目。

df.new <- df %>% 
  group_by(GroupID) %>% 
  mutate(Flag = as.numeric(any(Status == 'X')))

# A tibble: 10 x 4
# Groups:   GroupID [5]
      ID GroupID Status  Flag
   <int>   <int> <fct>  <dbl>
 1     1     100 A          1
 2     2     100 X          1
 3     3     102 A          0
 4     4     102 B          0
 5     5     103 B          1
 6     6     103 X          1
 7     7     104 X          1
 8     8     104 X          1
 9     9     105 A          0
10    10     105 C          0

答案 1 :(得分:2)

从底数R

ave(df$Status=='X',df$GroupID,FUN=any)
 [1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE

答案 2 :(得分:1)

Data.table方式:

library(data.table)
setDT(df)

df[ , flag := sum(Status == "X") > 0, by=GroupID]

答案 3 :(得分:1)

使用data.table

的替代方法
library(data.table)
dt <- read.table(stringsAsFactors = FALSE,text = "ID   GroupID    Status
                 1    100        A
                 2    100        X
                 3    102        A
                 4    102        B
                 5    103        B 
                 6    103        X
                 7    104        X
                 8    104        X
                 9    105        A
                 10   105        C", header=T)
setDT(dt)[,.(ID,Status, Flag=ifelse("X"%in% Status,1,0)),by=GroupID]

#returns
   GroupID ID Status Flag
 1:     100  1      A    1
 2:     100  2      X    1
 3:     102  3      A    0
 4:     102  4      B    0
 5:     103  5      B    1
 6:     103  6      X    1
 7:     104  7      X    1
 8:     104  8      X    1
 9:     105  9      A    0
10:     105 10      C    0

答案 4 :(得分:0)

带有base R的{​​{1}}选项

rowsum

或使用i1 <- with(df1, rowsum(+(Status == "X"), group = GroupID) > 0) transform(df1, Flag = +(GroupID %in% row.names(i1)[i1]))

table