【问题标题】:Frequency of two columns counting NAs in one column as zero frequency将一列中的 NA 计数为零频率的两列的频率
【发布时间】:2015-10-19 14:52:56
【问题描述】:

第 1 部分我有以下数据表。我想创建一个新列,其中包含每个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)]

所需的数据表如下:

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

第 2 部分 我还希望能够添加另一列,其中包含具有特定样式值的每个 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

奖励问题:您如何计算在 Part2 中给定的 style 值出现 id 的次数,而不是查看不同每个idstyle值,如下所示。

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

【问题讨论】:

  • 不确定第一个计数...例如,如果有另一个样式 B 的 id = 3,您可以在此示例中添加预期结果吗? (还要检查您的初始 data.table,因为它没有四个 id=4...)
  • 预期的输出与给定的输入不匹配。

标签: r data.table frequency


【解决方案1】:

这是一种可能性。基本上我们使用行子集来分配新列,然后将所有三个新列中的 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() 语句。

【讨论】:

  • 也不错!谢谢!
【解决方案2】:

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

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

【讨论】:

  • ifelse 应保存在条件向量 > 1 的情况下。any(..) 将始终生成长度为 1 的逻辑。在这种情况下,if(any(is.na(style))) 0L else .N 很可能是更好的控制流。但是对于他们都碰巧起作用的情况,比如这个,这可能是有争议的。
  • 在这种情况下,结果完全相同(我故意使用 ifelse 函数,因为我不喜欢单行 if 语句)。你觉得 ifelse 效率低吗?
  • 我认为它更“正确”。但我一直都在打破规范。这两个语句的行为不同,因为许多新用户可能认为它们可以互换。
  • 或者你可以完全避免它dt[, count := sum(!is.na(style)), id][,count2 := sum(count != 0), by= .(id, style)][]
  • 添加了奖励答案
猜你喜欢
  • 2012-06-08
  • 2021-05-28
  • 2019-06-14
  • 1970-01-01
  • 2017-04-20
  • 2017-01-27
  • 1970-01-01
  • 2021-09-02
相关资源
最近更新 更多