【问题标题】:Maintain NA's after aggregation R聚合 R 后保持 NA
【发布时间】:2014-09-23 17:49:03
【问题描述】:

我有一个如下的数据框

test_df<-data.frame(col1=c(1,NA,NA,4,5),col2=c(3,NA,NA,5,6),col3=c("a","b","c","d","c"))
test_df
 col1 col2 col3
   1    3    a
   NA   NA   b
   NA   NA   c
   4    5    d
   5    6    c

我正在根据 col3 聚合数据

agg_test<-aggregate(list(test_df$col1,test_df$col2),by=list(test_df$col3),sum,na.rm=T)
agg_test
Col3 col1 col2
 a    1    3
 b    0    0
 c    5    6
 d    4    5

根据我对求和正确的了解,我们需要明确定义要对 NA 执行的操作,在这种情况下,我已指定要从求和中删除 NA,我猜在内部 R 会将所有 NA 转换为 0 并且根据by条件总结。我需要以不同的方式处理数据中的 NA 和 0,因此必须保持有效的 NA(在这种情况下,b 的观察值是 NA 而不是 0)。我怎样才能做到这一点?

Expected o/p
Col3 col1 col2
a    1    3
b    NA   NA
c    5    6
d    4    5

【问题讨论】:

  • 您在寻找什么输出?现在您正在使用na.rm=T 来忽略 NA。和na.rm=F一样是你想要的吗?
  • 我希望 b 的值是 NA 而不是 0na.rm =F 不会汇总 c 的观察值,我如果有多个观察值并且它们具有NA,则希望同时处理这两种情况,输出应该是数字总和,如果观察结果仅为NA,则应保持NA
  • 在问题中显示您期望的输出。

标签: r dataframe data.table aggregate na


【解决方案1】:
 library(data.table)
 unique(setDT(test_df)[, lapply(.SD, function(x) 
                replace(x, !all(is.na(x)), sum(x, na.rm=TRUE))) , by=col3])

 #   col3 col1 col2
 #1:    a    1    3
 #2:    b   NA   NA
 #3:    c    5    6
 #4:    d    4    5

 test_df1 <- test_df
 test_df1$col2[2] <- 2
 unique(setDT(test_df1)[, lapply(.SD, function(x)
                replace(x, !all(is.na(x)), sum(x, na.rm=TRUE))) , by=col3])
 #  col3 col1 col2
 #1:    a    1    3
 #2:    b   NA    2
 #3:    c    5    6
 #4:    d    4    5

更新

或者使用@Arun 建议的简洁代码

 test_df1$col2[5] <- NA
 setDT(test_df1)[, lapply(.SD, 
             function(x) sum(x,na.rm= !all(is.na(x)))), by=col3] 
 #   col3 col1 col2
 #1:    a    1    3
 #2:    b   NA    2
 #3:    c    5   NA
 #4:    d    4    5

【讨论】:

  • @Arun 感谢提供更好、更优雅的条件代码。
  • @Arun 我猜代码中存在错误。我正在更新代码
  • 我明白了。然后可以简化为!all(is.na(x))
【解决方案2】:

听起来(根据您的 cmets 对澄清的要求)您希望汇总您的组,以便在所有值都缺失时获得 NA,否则您需要非缺失值的总和。您可以将aggregate 传递给具有此行为的用户定义函数:

aggregate(list(test_df$col1,test_df$col2), by=list(test_df$col3),
          function(x) ifelse(all(is.na(x)), NA, sum(x, na.rm=T)))
#   Group.1 c.1..NA..NA..4..5. c.3..NA..NA..5..6.
# 1       a                  1                  3
# 2       b                 NA                 NA
# 3       c                  5                  6
# 4       d                  4                  5

【讨论】:

  • 谢谢 josilber .. 这样做的好方法 :)
  • 我怎样才能将它复制到test_df[,list(sum(col1),sum(col2)),by=col3]的data.table语法中
  • @ghub24 我几乎可以用test_dt[,lapply(.SD, function(x) ifelse(all(is.na(x)), NaN, sum(x, na.rm=T))), by=col3, .SDcols=c("col1", "col2")] 复制它,但如果我使用NA 而不是NaN,它会给我带来错误。我对 data.table 包不是很熟悉,如果你在让它与该包正常工作时遇到问题,我建议发布一个单独的问题。
猜你喜欢
  • 2015-07-04
  • 2015-11-19
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
相关资源
最近更新 更多