【问题标题】:Number of non-NA records by column, grouped按列分组的非 NA 记录数
【发布时间】:2015-11-11 23:15:48
【问题描述】:

我有一个如下所示的 data.table:

> dt <- data.table(
  group1 = c("a", "a", "a", "b", "b", "b", "b"),
  group2 = c("x", "x", "y", "y", "z", "z", "z"),
  data1 = c(NA, rep(T, 3), rep(F, 2), "sometimes"),
  data2 = c("sometimes", rep(F,3), rep(T,2), NA))

> dt

   group1 group2     data1     data2
1:      a      x        NA sometimes
2:      a      x      TRUE     FALSE
3:      a      y      TRUE     FALSE
4:      b      y      TRUE     FALSE
5:      b      z     FALSE      TRUE
6:      b      z     FALSE      TRUE
7:      b      z sometimes        NA

我的目标是找出每个数据列中非 NA 记录的数量,按 group1group2 分组。

   group1 group2     data1     data2
1:      a      x         1         2
3:      a      y         1         1
4:      b      y         1         1
5:      b      z         3         2

我在处理数据集的另一部分时留下了这段代码,它没有 NAs 并且是合乎逻辑的:

dt[
  ,
  lapply(.SD, sum),
  by = list(group1, group2),
  .SDcols = c("data3", "data4")
]

但它不适用于 NA 值或非逻辑值。

【问题讨论】:

  • lapply() 的使用与您在基础 R 中的使用方式没有什么不同。

标签: r data.table


【解决方案1】:
dt[, lapply(.SD, function(x) sum(!is.na(x))), by = .(group1, group2)]
#   group1 group2 data1 data2
#1:      a      x     1     2
#2:      a      y     1     1
#3:      b      y     1     1
#4:      b      z     3     2

【讨论】:

  • 谢谢。我没有想到在 j 中定义一个函数 - 让一切变得干净整洁。
【解决方案2】:

另一种选择是melt/dcast,以避免按列操作。这将删除NAs 并默认使用length 函数

dcast(melt(dt, id = c("group1", "group2"), na.rm = TRUE), group1 + group2 ~ variable) 
# Aggregate function missing, defaulting to 'length'
#    group1 group2 data1 data2
# 1:      a      x     1     2
# 2:      a      y     1     1
# 3:      b      y     1     1
# 4:      b      z     3     2

【讨论】:

    【解决方案3】:

    使用dplyr(在 David Arenburg 和 eddi 的帮助下):

    library(dplyr)
    dt %>% group_by(group1, group2) %>% summarise_each(funs(sum(!is.na(.))))
    Source: local data table [4 x 4]
    Groups: group1
    
      group1 group2 data1 data2
    1      a      x     1     2
    2      a      y     1     1
    3      b      y     1     1
    4      b      z     3     2
    

    【讨论】:

    • 我相当肯定 dplyr 有某种 *_each 函数(我永远记不起那个包的所有额外函数)可以处理每列的手动混乱跨度>
    • @eddi 的意思可能类似于dt %&gt;% group_by(group1, group2) %&gt;% summarise_each(funs(sum(!is.na(.))))
    • 感谢大家的建议。我更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 2014-01-31
    • 2017-05-06
    • 2021-12-19
    • 2012-09-05
    相关资源
    最近更新 更多