【问题标题】:Comparing group means比较组均值
【发布时间】:2019-07-03 23:41:12
【问题描述】:

我有一个如下所示的数据集:

library(data.table)
df <- fread(
  "A   B   C   fac   H   I   J   iso   year   matchcode
     0   1   1   NA   0   1   0   NLD   2009   NLD2009
     1   0   2   NA   1   0   1   NLD   2009   NLD2009
     0   0   3   B    1   0   0   AUS   2011   AUS2011
     1   0   4   B    0   1   0   AUS   2011   AUS2011
     0   1   7   NA   0   0   0   NLD   2008   NLD2008
     1   0   1   A    0   1   0   NLD   2008   NLD2008
     0   0   3   B    1   0   0   AUS   2012   AUS2012
     1   0   4   B    0   1   0   AUS   2012   AUS2012",
  header = TRUE
)

对于我想检查的每个国家/地区,C 的平均值是否随时间变化。所以我做了:

setDT(df)[, c("MeanValue_C", "Residual_C") := {m= mean(C, na.rm=TRUE);list(m, C-m)}, by=list(iso, year)]

这基本上给了我想要的信息。但是没有任何有用的格式。我试着做table(df$MeanValue_C, df$matchcode),但这造成了很大的混乱,因为实际的数据集有大约 100 个国家,有 2 年或更长时间。

在不创建额外数据表的情况下,比较每个国家/地区的组均值的最简单方法是什么?

最好是这样的:

df2 <- fread(
  "C   iso   year   matchcode
     1.5   NLD   2009   NLD2009
     3.5   AUS   2011   AUS2011
     4     NLD   2008   NLD2008
     3.5   AUS   2012   AUS2012",
  header = TRUE
)

【问题讨论】:

  • 不清楚你到底在追求什么。你有逐年的手段;你想形象化他们吗?做一些统计测试?总结一下?
  • 我添加了一些示例输出。我想目前我只想总结一下它们..

标签: r data.table mean


【解决方案1】:

这是一个开始。您可以在每个国家/地区的年平均值上运行summary,以获取每个国家/地区的一些基本样本时刻。 summary 返回一个 5 位数汇总 + 均值的向量; as.list 对此进行转换,因此每个元素都是一列。 keyby 对分组进行排序(即在执行操作后运行setkey):

df[ , .(c_mean = mean(C, na.rm = TRUE)), keyby = .(iso, year, matchcode)
    ][ , as.list(summary(c_mean)), keyby = .(iso, matchcode)]
#    iso matchcode Min. 1st Qu. Median Mean 3rd Qu. Max.
# 1: AUS   AUS2011  3.5     3.5    3.5  3.5     3.5  3.5
# 2: AUS   AUS2012  3.5     3.5    3.5  3.5     3.5  3.5
# 3: NLD   NLD2008  4.0     4.0    4.0  4.0     4.0  4.0
# 4: NLD   NLD2009  1.5     1.5    1.5  1.5     1.5  1.5

不幸的是,summary 的输出类型不能保证像这里那样长度为 5。特别是对于数字,如果输入中有任何 NA_real_ 值,则长度为 6。由于您已经运行了na.rm = TRUE,这只有在iso-matchcode 组合没有非NA 值的情况下才有可能(要确认这一点,请运行summary(mean(NA_real_, na.rm = TRUE)))。要继续,例如,您可以预先删除这些值:

df[ , keyby = .(iso, year, matchcode),
   if (!all(is.na(C)) .(c_mean = mean(C, na.rm = TRUE)), 
    ][ , as.list(summary(c_mean)), keyby = .(iso, matchcode)]

或者在中间放下它们:

df[ , .(c_mean = mean(C, na.rm = TRUE)), keyby = .(iso, year, matchcode)
    ][!is.na(c_mean), as.list(summary(c_mean)), keyby = .(iso, matchcode)]

或者,如果您不想丢失该信息(缺少某些组合),您可以强制输出更加一致:

df[ , .(c_mean = mean(C, na.rm = TRUE)), keyby = .(iso, year, matchcode)
    ][ , {
      s = summary(c_mean)
      if (length(s) == 5L) s = c(s, `NA's` = 0L)
      as.list(s)
    }, keyby = .(iso, matchcode)]

(您可以通过运行print(summary.default) 来检查summary.default 的代码,以确保这应该有效)

【讨论】:

  • 这很整洁。非常感谢!
  • 对于我的实际数据集,解决方案给出了错误:Error in [.data.table(df[, .(c_mean = mean(C, na.rm = TRUE)), : j doesn't evaluate to the same number of columns for each group 你知道可能是什么问题吗?会不会是在某些国家/地区年份 C 根本不可用时发生这种情况?
  • @Tom 尝试将[!is.na(c_mean)] 作为第二个i 子句。 summary(mean(NA_real_, na.rm = TRUE)) 给出 6 列...
  • 我刚刚验证了问题确实是C 在某些国家/地区是 NA (并且它适用于没有 NA 的另一个变量)。但是,我并不完全理解您在评论中打算做什么。是否可以准确地告诉我您对编辑的意思?
  • 我明白你的意思了,现在可以了!非常感谢您的帮助!
【解决方案2】:

没有明确说明解决方案必须是data.table,但获得所述输出的tidyverse 解决方案是:

library(tidyverse)

df %>% 
  group_by(iso, year, matchcode) %>% 
  summarise(C = mean(C)) %>% 
  select(C, iso, year, matchcode) 

# A tibble: 4 x 4
# Groups:   iso, year [4]
      C iso    year matchcode
  <dbl> <chr> <int> <chr>    
1   3.5 AUS    2011 AUS2011  
2   3.5 AUS    2012 AUS2012  
3   4   NLD    2008 NLD2008  
4   1.5 NLD    2009 NLD2009 

【讨论】:

    猜你喜欢
    • 2012-04-16
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 2020-10-10
    • 2015-05-01
    • 1970-01-01
    相关资源
    最近更新 更多