R:运行 使用 dplyr 按组对前几年进行 t 检验

R: Run t-test on previous years by group using dplyr

我有一个包含不同组、年份及其值的数据框,例如:

data <- data.frame(
  group = c(rep('A', 120), rep('B', 120)),
  year  = rep(c(rep('2013-2014', 40), rep('2014-2015', 40), rep('2015-2016', 40)), 2),
  value = rnorm(240)
)

对于每个组中的每一年,我想 运行 进行 t 检验以查看这些值是否与前几年有显着差异(我一直在使用函数 t.test(x, y, var.equal = TRUE) 一次性执行此操作)

我想 return 数据框和 p 值,或者最好是使用 gtools::stars.pval() 生成的重要星星。所以 return 类似下面的内容

group year      significance
A     2013-2014 NA
A     2014-2015 **
A     2015-2016 ***
B     2013-2014 NA
B     2014-2015
B     2015-2016

其中,2014-2015 和 2013-2014 之间差异的 p 值对于 'A' 在 0.001 和 0.01 之间,而 2015-2015 和 2014-2015 之间差异的 p 值对于 A <0.001。没有证据表明 B.

在任何年份有任何显着差异

不能保证每个组的年数都相同。

最好最快的方法是什么?我希望我可以按组和年份使用 dplyr 和 group_by 来做到这一点?

另一种选择是汇总数据框,将一个单元格中的所有值存储为列表(是的,您可以这样做 - 数据框可以在其中嵌套列表!)

使用 dplyr:

df=tbl_df(data)
df=arrange(df,group,year) %>% group_by(group,year) %>% summarise(values=list(value))
df=mutate(df,prev_values=lag(values))
df=group_by(df,group,year)
df=filter(df,!any(is.na(unlist(prev_values))))
df=mutate(df,p_value=t.test(unlist(values),unlist(prev_values),var.equal=TRUE)$p.value) %>% print

  group      year    values prev_values   p_value
1     A 2014-2015 <dbl[40]>   <dbl[40]> 0.7894477
2     A 2015-2016 <dbl[40]>   <dbl[40]> 0.2385581
3     B 2014-2015 <dbl[40]>   <dbl[40]> 0.3084138
4     B 2015-2016 <dbl[40]>   <dbl[40]> 0.2557849

我非常喜欢@MaksimGayduk 的解决方案。特别是 "trick" 和 summarise(values=list(value))。以前没用过,感觉很有用。我的替代但类似的解决方案是基于 dplyrbroom 包。

不同之处在于 (a) 我首先使用感兴趣的 t.tests 的适当信息创建一个 table,然后我从初始 df 数据中调用相应的值帧,和 (b) 扫帚包 returns 来自 t.test 的所有信息输出为数据帧,您可以从中选择 p.value 或您需要的任何其他内容。

set.seed(15)

df <- data.frame(
  group = c(rep('A', 120), rep('B', 120)),
  year  = rep(c(rep('2013-2014', 40), rep('2014-2015', 40), rep('2015-2016', 40)), 2),
  value = rnorm(240)
)


library(dplyr)
library(broom)

df %>% 
  select(group, year) %>%
  arrange(group,year) %>%
  distinct() %>%
  group_by(group) %>%
  mutate(lag_year = lag(year)) %>%
  filter(!is.na(lag_year)) %>%
  group_by(group, year, lag_year) %>%
  do(tidy(t.test(df$value[df$year==.$year & df$group==.$group], 
                 df$value[df$year==.$lag_year & df$group==.$group])))


# Source: local data frame [4 x 11]
# Groups: group, year, lag_year [4]
# 
# group      year  lag_year    estimate   estimate1   estimate2  statistic   p.value parameter   conf.low conf.high
# (fctr)    (fctr)    (fctr)       (dbl)       (dbl)       (dbl)      (dbl)     (dbl)     (dbl)      (dbl)     (dbl)
# 1      A 2014-2015 2013-2014 -0.14570115  0.04597952  0.19168066 -0.6752803 0.5016009  74.05084 -0.5756153 0.2842130
# 2      A 2015-2016 2014-2015 -0.02752882  0.01845069  0.04597952 -0.1162621 0.9077438  77.96192 -0.4989302 0.4438726
# 3      B 2014-2015 2013-2014  0.39565472  0.05703318 -0.33862155  1.5776920 0.1187303  77.10933 -0.1037022 0.8950116
# 4      B 2015-2016 2014-2015 -0.07423089 -0.01719771  0.05703318 -0.3048113 0.7613240  77.77704 -0.5590850 0.4106233