组别差异

Difference by group

很可能是重复的,但我没有找到答案:

我想使用 dplyrs summarise_all 在每一列的第一行和最后一行之间按组构建差异。通过添加具有差异的新行或通过创建新数据框。

假设我有这个 df:

df <- data.frame(unit=rep(1:250, 4),  
             year=rep(c(2012, 2013, 2014, 2015), each=250),
             replicate(10,sample(0:50000,1000,rep=TRUE)))

我想根据单位了解每一列的 2012 年值和 2015 年值之间的差异。

这不起作用:

df <- df %>% 
      group_by(unit) %>% 
      summarise_all(funs(diff))

您必须将数据过滤为每个单位仅包含两个值,即 2012 年和 2015 年:

df %>% 
  filter(year %in% c(2012, 2015)) %>% 
  group_by(unit) %>% 
  summarise_all(funs(diff))

# # A tibble: 250 x 12
# unit  year     X1     X2     X3     X4     X5     X6     X7     X8     X9    X10
# <int> <dbl>  <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>
#   1     1    3.   4509 -12192   6935  -5226   3538  14019 -10962  -3310  34014 -14668
# 2     2    3.  22811  -8568 -34469 -11743 -11569   7713  -5074  26502   6498  23340
# 3     3    3.  16886   8533 -16659   1585  17773 -30438   4723  -8048 -12521 -20980
# 4     4    3.  16888  -1732 -17721  26901 -24762  -9469  12574 -10933  17781  26397
# 5     5    3. -12643   -465  18461 -11637  40236  33825 -14037  18219  26781   7247
# 6     6    3. -27066 -14527 -18784 -13287  31836 -14046  46221   8493  20288 -17644
# 7     7    3.  -2777 -16123 -23697  -9932  18175 -20991 -38581   8505 -14498 -18397
# 8     8    3.  36854  -1865  -7608 -11197 -25044    344  24447   8201 -14640 -12060
# 9     9    3.  -6240  10678   2463  -3134   4442  10373   5075  -6204    218  20438
# 10    10    3.  -3496  -3284   2864  25562  -3473   4240 -17616  18310 -21326  10261
# # ... with 240 more rows

您必须这样做的原因是,否则 diff 会计算年份之间的所有差异,这相当于每单位超过 1 个结果,因此 summarise_all 无法处理.

问题是 diff 没有达到您的预期。它有效地计算了 x[-n] - x[-1].

一个更通用的解决方案,如果缺少 2012 或 2015,可以通过索引:

df %>% 
  group_by(unit) %>% 
  arrange(unit, year) %>%
  summarise_at(vars(starts_with('X')), funs(.[1] - .[n()]))

或者创建一个更漂亮的函数:

diff_ends <- function(x, order_var) {
  x[which.min(order_var)] - x[which.max(order_var)]
}
df %>% group_by(unit) %>%
  summarise_at(vars(starts_with('X')), funs(diff_ends(., year)))
df %>% 
  group_by(unit) %>% 
  slice(c(1, n()) ) %>% 
    summarise_at(vars(X1:X10), diff)