两列的频率将一列中的 NA 计为零频率

Frequency of two columns counting NAs in one column as zero frequency

第 1 部分 我有以下数据 table。我想创建一个新列,其中包含每个 id 的出现次数,其中有任何样式值,NA 除外。主要问题是我不知道如何处理NA。目前,当出现 NA 时,我得到的频率为 1.

id    style   
1     A    
1     A    
2     A    
2     B    
3     NA    
4     A    
4     C   
5     NA

我尝试使用以下内容,但它仍然计算 NA 个值

dt[, allele_count := .N, by = list(pat_id, style)]

所需数据table如下:

id    style   count
1     A       2
1     A       2
2     A       2
2     B       2
3     NA      0
4     A       4
4     B       4
4     B       4
4     C       4
5     NA      0

Part2 我还希望能够添加另一列,其中包含具有特定样式值的每个 id 的出现次数。

id    style   count2
1     A       2
1     A       2
2     A       1
2     B       1
3     NA      0
4     A       1
4     B       2
4     B       2
4     C       1
5     NA      0

奖金问题:而不是像第 2 部分那样查看给定 style 值出现 id 的次数 ,如何计算每个 id 不同 style 值的数量,如下所示。

id    style   count3
1     A       1
1     A       1
2     A       2
2     B       2
3     NA      0
4     A       3
4     B       3
4     B       3
4     C       3
5     NA      0

这是一个可能的解决方案:

library(data.table)

dt <- data.table(id=c(1,1,2,2,3,4,4,5),
                 style=c('A','A','A','B',NA,'A','C',NA))

# count = number of ids having ALL styles defined
dt[, count := if(any(is.na(style))) 0L else .N, by = id]
# count2 = number of id-style occurrences (0 if style = NA)
dt[, count2 := if(is.na(style)) 0L else .N, by = .(id, style)]


> dt
   id style count count2
1:  1     A     2      2
2:  1     A     2      2
3:  2     A     2      1
4:  2     B     2      1
5:  3    NA     0      0
6:  4     A     2      1
7:  4     C     2      1
8:  5    NA     0      0

奖金:

dt[, count3 := uniqueN(na.omit(style)), by = id]

> dt
   id style count count2 count3
1:  1     A     2      2      1
2:  1     A     2      2      1
3:  2     A     2      1      2
4:  2     B     2      1      2
5:  3    NA     0      0      0
6:  4     A     2      1      2
7:  4     C     2      1      2
8:  5    NA     0      0      0

这是一种可能。基本上我们使用行子集来分配新列,然后在最后用零替换所有三个新列中的 NA 值。

nna <- !is.na(dt$style) ## so we don't have to call it four times
dt[nna, count := .N, by = id][nna, count2 := .N, by = .(id, style)][
    nna, count3 := uniqueN(style), by = id][!nna, names(dt)[3:5] := 0L]

这导致

   id style count count2 count3
1:  1     A     2      2      1
2:  1     A     2      2      1
3:  2     A     2      1      2
4:  2     B     2      1      2
5:  3    NA     0      0      0
6:  4     A     2      1      2
7:  4     C     2      1      2
8:  5    NA     0      0      0

或者您可以将其简化为以下内容,然后根据需要对列重新排序。

dt[nna, c("count", "count3") := .(.N, uniqueN(style)), by = id][
    nna, count2 := .N, by = .(id, style)][!nna, names(dt)[3:5] := 0L]

请注意,此方法与其他发布的答案非常相似。我不确定这两者中哪一个是首选方法,行子集或 if() 语句。