按时间和 ID 减去行

Subtract rows by time and ID

我有这样的数据集:

set.seed(10)
df <- data.frame(
Year = rep(2000, times=16),
Month = rep(1:2, each=8),
group = rep(c("ABC","ABc","Abc","AbC","aBC","aBc","abc", "abC"),times=2),
A_gr = rep(c("A","A","A","A","a","a","a","a"), times=2),
V = rnorm(16)
)

其中A、B、C可以是大写字母,也可以是小写字母。 对于每个时间点(月 + 年)和组组合,我现在想从小写字母版本中减去大写字母版本的 V 值。所以 aBC-ABC、aBc-ABc 等

只有 2 个组字母,我设法通过 order、list 和 by 做到了,但我不能在这里工作。我也尝试过 plyr 但都没有成功。有什么想法吗?

另外我想知道是否可以一步从小写字母的总和中减去所有四个大写字母的总和,所以(aBC+aBc+abc+abC)-(ABC+ABc+ Abc+AbC)

这是一种转换数据的方法,方法是从组列中删除 aA 信息,因为它也由 A_gr 提供,然后使用 tidyr 包将数据从 long 格式转换为 wide 格式,这使得计算差异变得更加容易。

library(dplyr); library(tidyr)
df %>% mutate(group = gsub("[A|a]", "", group)) %>% 
       spread(A_gr, V) %>% mutate(diffV = A - a) %>% 
       select(Year, Month, group, diffV)

  Year Month group    diffV
1 2000     1    bc -0.16325
2 2000     1    bC -0.23549
3 2000     1    Bc -0.57405
4 2000     1    BC -0.27580
5 2000     2    bc  0.36039
6 2000     2    bC  0.66643
7 2000     2    Bc -1.24392
8 2000     2    BC -1.38844

我们也可以用 data.table 来做到这一点。将 'data.frame' 转换为 'data.table' (setDT(df)),通过使用 [=14] 将 'group' 中的第一个字符更改为大写来创建另一个分组变量 ('gr') =],然后在 by 中与 'Month' 和 'Year' 一起使用,得到 "A" 和 "a" 对应的 'V' 之间的差异在 'A_gr' 中,并将 'gr' 分配给 NULL(如果需要)。

library(data.table)
setDT(df)[, .(group = paste(group[2L],group[1L], 
        sep="-"),Diffs=V[A_gr=="A"]- V[A_gr=="a"]), 
       by =  .(gr=sub("(.)", "\U\1", group, perl=TRUE), Month, Year)][, gr:= NULL][]
#   Month Year   group      Diffs
#1:     1 2000 aBC-ABC -0.2757990
#2:     1 2000 aBc-ABc -0.5740468
#3:     1 2000 abc-Abc -0.1632544
#4:     1 2000 abC-AbC -0.2354917
#5:     2 2000 aBC-ABC -1.3884391
#6:     2 2000 aBc-ABc -1.2439231
#7:     2 2000 abc-Abc  0.3603894
#8:     2 2000 abC-AbC  0.6664342

或者使用 dcast from data.table 从 'long' 转换为 'wide' 格式后通过提取 [=18 创建另一个变量 ('gr') =] 在 'group' 中。我们从 dcast 输出中获取 "V_A" 和 "V_a" 列之间的差异。

setDT(df)[, gr:= substring(group, 2)]
dcast(df, Year+Month+gr~A_gr, value.var=c("V", "group"))[, 
  .(group = paste(group_A, group_a, sep="-"), Diffs = V_A- V_a), .(Year, Month)]
#   Year Month   group      Diffs
#1: 2000     1 ABC-aBC -0.2757990
#2: 2000     1 ABc-aBc -0.5740468
#3: 2000     1 AbC-abC -0.2354917
#4: 2000     1 Abc-abc -0.1632544
#5: 2000     2 ABC-aBC -1.3884391
#6: 2000     2 ABc-aBc -1.2439231
#7: 2000     2 AbC-abC  0.6664342
#8: 2000     2 Abc-abc  0.3603894