R data.table:根据其他列的值标记连续值的“标识”?

时间:2017-04-24 20:41:46

标签: r dataframe data.table

我有以下data.table(它更大,但显示了这个结构)

library(data.table)

dt = data.table(first_column = c("A", "B", "B", "B", "C", "A", "A", "A", "D", "B", "A", "A"), second_column =c(0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0))

> dt
    first_column second_column
 1:            A             0
 2:            B             1
 3:            B             1
 4:            B             1
 5:            C             0
 6:            A             0
 7:            A             0
 8:            A             1
 9:            D             1
10:            B             1
11:            A             1
12:            A             0
....

结果data.table应如下所示:

  first_column  second_column    identity    percent
0             A              0           0          0
1             B              1          AB        1.0
2             B              1          AB        1.0
3             B              1          AB        1.0
4             C              0           0          0
5             A              0           0          0
6             A              0           0          0
7             A              1       mixed       0.75  # 3/4, 3-AB, 4-total
8             D              1       mixed       0.75
9             B              1       mixed       0.75
10            A              1       mixed       0.75
11            A              0           0          0 
....

first_column对于每一行A,B,C和D.在第二列中,有一个表示一组值的二进制标签。所有1的连续分组都是唯一的“组”,例如第1-3行是一组,第7-10行是另一组。

我想通过“AB”(该组仅由A或B组成),“CD”(该组仅由C或D组成)或“标记”这些组中的每一组。混合“(如果有混合物,例如所有B和一个C)。知道“如何”混合这些分组中的一些百分比,即AB在总标签中的百分比也是有用的。如果它只是A或B,则标识应为AB。如果它只是C或D,则标识应为CD。它是A,B,C和/或D的混合物,然后混合。百分比是(AB行数#)/(总行数#)

对于identity列,我怀疑可以使用ifelse()语句,例如。

dt$identity = ifelse( ((dt$second_column == 1) & (dt$first_column == "A") & (dt$first_column == "B") & (dt$first_column != "C") & (dt$first_column != "D")), "AB", 0)   

dt$identity = ifelse( ((dt$second_column == 1) & (dt$identity != "AB") & (dt$first_column == "C") & (dt$first_column == "D") & (dt$first_column != "A") & (dt$first_column != "B")), "CD", 0)  

但是我在定义“混合案例”时陷入了逻辑ifelse()困难。我也完全不确定如何衡量AB /所有行的百分比。

1 个答案:

答案 0 :(得分:3)

您可以使用rleiddata.table来获得所需内容。我使用rleid获取分组变量,然后根据您对每个组的条件创建标识和百分比变量。感谢@DavidArenburg的建议!

dt[,c("identity", "percent") := list(if(all(first_column == "A") | all(first_column == "B")) "AB"
                                      else if (all(first_column == "C") | all(first_column == "D")) "CD"
                                      else "mixed", sum(first_column %in% c("A","B")) / .N), by =  rleid(second_column)]
dt[second_column==0, c("identity","percent") := list("0", 0)]

dt
 #       first_column second_column identity percent
 #1:            A             0        0    0.00
 #2:            B             1       AB    1.00
 #3:            B             1       AB    1.00
 #4:            B             1       AB    1.00
 #5:            C             0        0    0.00
 #6:            A             0        0    0.00
 #7:            A             0        0    0.00
 #8:            A             1    mixed    0.75
 #9:            D             1    mixed    0.75
#10:            B             1    mixed    0.75
#11:            A             1    mixed    0.75
#12:            A             0        0    0.00

你可以将这些电话联系起来,但我不是为了便于阅读。