在R的data.table中进行条件唯一计数

5
我想按组对我的数据集中的冲突数量进行计数。我觉得在data.table中肯定有一种简单的方法来做到这一点,但似乎无法弄清楚。我已经创建了一个虚拟变量,以告诉我数据表的每一行是否存在冲突。
testDT <- data.table(Name = c(rep('A',6),rep('B',5)),
                     Division = c(rep(11,6),rep(12,5)),
                     ID = c(205,205,NA,201,201,201,203,203,203,204,NA),
                     Conflict = c(0,0,0,1,1,1,1,1,1,1,0))

我需要统计每个名字和部门组合中,具有冲突标志为1的非NA ID 的独立数量,并将该数量应用于新列中。答案如下:

testDT[, Count := c(rep(1,6),rep(2,5))]

    Name Division  ID Conflict Count
 1:    A       11 205        0     1
 2:    A       11 205        0     1
 3:    A       11  NA        0     1
 4:    A       11 201        1     1
 5:    A       11 201        1     1
 6:    A       11 201        1     1
 7:    B       12 203        1     2
 8:    B       12 203        1     2
 9:    B       12 203        1     2
10:    B       12 204        1     2
11:    B       12  NA        0     2

我一直在考虑使用sum(!is.na(unique(ID)))的一些用法,但我不确定如何有条件地计算唯一值而不在数据表的i部分创建条件(Conflict == 1)

2个回答

13
你可以在 data.table 的方括号 [] 内使用条件对变量 ID 进行子集操作,然后计算唯一值的数量:

你可以在 data.table 的方括号 [] 内使用条件对变量 ID 进行子集操作,然后计算唯一值的数量:

library(data.table)
testDT[, Count := uniqueN(ID[!is.na(ID) & Conflict == 1]), by=.(Name, Division)]
testDT
#     Name Division  ID Conflict Count
#  1:    A       11 205        0     1
#  2:    A       11 205        0     1
#  3:    A       11  NA        0     1
#  4:    A       11 201        1     1
#  5:    A       11 201        1     1
#  6:    A       11 201        1     1
#  7:    B       12 203        1     2
#  8:    B       12 203        1     2
#  9:    B       12 203        1     2
# 10:    B       12 204        1     2
# 11:    B       12  NA        0     2

按照你的逻辑:

testDT[, Count := sum(!is.na(unique(ID[Conflict == 1]))), by=.(Name, Division)]

为什么在 j 中要加入条件?我想这会使速度变慢。testDT[!is.na(ID) & Conflict == 1, Count := uniqueN(ID), by = .(Name, Division)] 在整个表上执行所有逻辑测试,而不是在每个组上进行测试。除非我漏掉了什么。 - MichaelChirico
1
哦,我明白了。这将为那些行分配NA。这取决于@shughes是否介意... - MichaelChirico
1
哦,还有一件事。uniqueN有一个na.rm参数,所以你可以使用它来代替在!is.na上进行条件判断。根据你使用的版本,这可能会导致错误,不过我已经更新了才解决了这个问题(https://github.com/Rdatatable/data.table/issues/1771)。 - Frank

1
这是一个使用 dplyr 的选项。
library(dplyr)
testDT %>%
    group_by(Name, Division) %>% 
    mutate(Count = n_distinct(ID[!is.na(ID) & Conflict==1]))
#    Name Division    ID Conflict Count
#   <chr>    <dbl> <dbl>    <dbl> <int>
#1      A       11   205        0     1
#2      A       11   205        0     1
#3      A       11    NA        0     1
#4      A       11   201        1     1
#5      A       11   201        1     1
#6      A       11   201        1     1
#7      B       12   203        1     2
#8      B       12   203        1     2
#9      B       12   203        1     2
#10     B       12   204        1     2
#11     B       12    NA        0     2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接