几天前我发布了这个问题,但我被告知我的描述太混乱了。然而,在澄清我的问题并添加一个例子之后,这个问题没有得到任何进一步的关注。由于我仍然需要一个解决方案,我删除了旧问题,现在将其发布为希望更好的表述。
以下示例说明了我的问题。
我有两个对象。其中第一个是描述每个人( id )组( id )的数据框,这是s(他)采取行动的一年( do.year )以及2010年至2015年之间每年的变量值( var )( var.year )。
set.seed(1)
df <- data.frame(
id = rep(1:3, each = 6),
group = c(rep("a", 12), rep("b", 6)),
do.year = rep(sample(2011:2013), each = 6),
var = runif(18),
var.year = 2010:2015)
df
id group do.year var var.year
1 1 a 2011 0.90820779 2010
2 1 a 2011 0.20168193 2011
3 1 a 2011 0.89838968 2012
4 1 a 2011 0.94467527 2013
5 1 a 2011 0.66079779 2014
6 1 a 2011 0.62911404 2015
7 2 a 2013 0.06178627 2010
8 2 a 2013 0.20597457 2011
9 2 a 2013 0.17655675 2012
10 2 a 2013 0.68702285 2013
11 2 a 2013 0.38410372 2014
12 2 a 2013 0.76984142 2015
13 3 b 2012 0.49769924 2010
14 3 b 2012 0.71761851 2011
15 3 b 2012 0.99190609 2012
16 3 b 2012 0.38003518 2013
17 3 b 2012 0.77744522 2014
18 3 b 2012 0.93470523 2015
第二个对象包含 a 和 b 组的数据框,还包含每年之间变量( var )的值2010年和2015年( var.year ),但这些是组成员的平均值。它是一个数据帧列表,但如果需要,也可以转换为单个数据帧。
avg <- list(
"a" = data.frame(var.year = 2010:2015, var = runif(6)),
"b" = data.frame(var.year = 2010:2015, var = runif(6)))
avg
$a
var.year var
1 2010 0.21214252
2 2011 0.65167377
3 2012 0.12555510
4 2013 0.26722067
5 2014 0.38611409
6 2015 0.01339033
$b
var.year var
1 2010 0.3823880
2 2011 0.8696908
3 2012 0.3403490
4 2013 0.4820801
5 2014 0.5995658
6 2015 0.4935413
我的目标是将每个人的结果指标与特定年份( do.year )中相应比较组的结果指标进行比较。因此,对于每个人( id ),我想在采取行动的一年中采用变量( var )的值( do.year )并从该值中减去同年的组平均值( av avg )( var.year )。每个人的结果将存储在一个新变量 diff.var 中。
我只有几周的R经验,所以我的解决方案是合并每个组(和变量)的数据集,然后进行计算(如下)。但是,由于我的原始数据集涉及7个组和6个变量,因此会产生大约1000行代码。我也试过循环,但无法在任何地方正确定义循环变量。
df.a <- merge(df, avg[["a"]], by = "var.year")
df.a$diff.var[df.a$group == "a" & df.a$var.year == df.a$do.year] <-
df.a$var.x[df.a$group == "a" & df.a$var.year == df.a$do.year] -
df.a$var.y[df.a$group == "a" & df.a$var.year == df.a$do.year]
df.a
var.year id group do.year var.x var.y diff.var
1 2010 1 a 2011 0.90820779 0.21214252 NA
2 2010 2 a 2013 0.06178627 0.21214252 NA
3 2010 3 b 2012 0.49769924 0.21214252 NA
4 2011 1 a 2011 0.20168193 0.65167377 -0.4499918
5 2011 2 a 2013 0.20597457 0.65167377 NA
6 2011 3 b 2012 0.71761851 0.65167377 NA
7 2012 1 a 2011 0.89838968 0.12555510 NA
8 2012 2 a 2013 0.17655675 0.12555510 NA
9 2012 3 b 2012 0.99190609 0.12555510 NA
10 2013 1 a 2011 0.94467527 0.26722067 NA
11 2013 2 a 2013 0.68702285 0.26722067 0.4198022
12 2013 3 b 2012 0.38003518 0.26722067 NA
13 2014 1 a 2011 0.66079779 0.38611409 NA
14 2014 2 a 2013 0.38410372 0.38611409 NA
15 2014 3 b 2012 0.77744522 0.38611409 NA
16 2015 1 a 2011 0.62911404 0.01339033 NA
17 2015 2 a 2013 0.76984142 0.01339033 NA
18 2015 3 b 2012 0.93470523 0.01339033 NA
df.b <- merge(df, avg[["b"]], by = "var.year")
df.b$diff.var[df.b$group == "b" & df.b$var.year == df.b$do.year] <-
df.b$var.x[df.b$group == "b" & df.b$var.year == df.b$do.year] -
df.b$var.y[df.b$group == "b" & df.b$var.year == df.b$do.year]
df.b
var.year id group do.year var.x var.y diff.var
1 2010 1 a 2011 0.90820779 0.3823880 NA
2 2010 2 a 2013 0.06178627 0.3823880 NA
3 2010 3 b 2012 0.49769924 0.3823880 NA
4 2011 1 a 2011 0.20168193 0.8696908 NA
5 2011 2 a 2013 0.20597457 0.8696908 NA
6 2011 3 b 2012 0.71761851 0.8696908 NA
7 2012 1 a 2011 0.89838968 0.3403490 NA
8 2012 2 a 2013 0.17655675 0.3403490 NA
9 2012 3 b 2012 0.99190609 0.3403490 0.6515571
10 2013 1 a 2011 0.94467527 0.4820801 NA
11 2013 2 a 2013 0.68702285 0.4820801 NA
12 2013 3 b 2012 0.38003518 0.4820801 NA
13 2014 1 a 2011 0.66079779 0.5995658 NA
14 2014 2 a 2013 0.38410372 0.5995658 NA
15 2014 3 b 2012 0.77744522 0.5995658 NA
16 2015 1 a 2011 0.62911404 0.4935413 NA
17 2015 2 a 2013 0.76984142 0.4935413 NA
18 2015 3 b 2012 0.93470523 0.4935413 NA
如何在R中解决这个问题?基础R或data.table解决方案将是首选。
答案 0 :(得分:3)
如果你想要一个data.table
解决方案,那么这是一个可能的解决方案。我建议您先将列表转换为data.table
列group
。只需var.year
和group
加入do.year == var.year
,即时创建diff.var
。我还假设您并没有真正尝试为每个组创建相同的数据集,而只是根据您的规则为avg
加入的原始数据集。类似于以下内容
library(data.table)
### Create a group column for each list and convert to a data.table
avg <- rbindlist(Map(cbind, avg, group = names(avg)))
### join by var.year and group while do.year == var.year and create diff.var on the fly
setDT(df)[do.year == var.year,
diff.var := var - avg[copy(.SD), var, on = c("var.year", "group")]]
df
# id group do.year var var.year diff.var
# 1: 1 a 2011 0.90820779 2010 NA
# 2: 1 a 2011 0.20168193 2011 -0.4499918
# 3: 1 a 2011 0.89838968 2012 NA
# 4: 1 a 2011 0.94467527 2013 NA
# 5: 1 a 2011 0.66079779 2014 NA
# 6: 1 a 2011 0.62911404 2015 NA
# 7: 2 a 2013 0.06178627 2010 NA
# 8: 2 a 2013 0.20597457 2011 NA
# 9: 2 a 2013 0.17655675 2012 NA
# 10: 2 a 2013 0.68702285 2013 0.4198022
# 11: 2 a 2013 0.38410372 2014 NA
# 12: 2 a 2013 0.76984142 2015 NA
# 13: 3 b 2012 0.49769924 2010 NA
# 14: 3 b 2012 0.71761851 2011 NA
# 15: 3 b 2012 0.99190609 2012 0.6515571
# 16: 3 b 2012 0.38003518 2013 NA
# 17: 3 b 2012 0.77744522 2014 NA
# 18: 3 b 2012 0.93470523 2015 NA