如何将数据框的值与另一个数据框的值进行比较?
How to compare values of a data frame to values in another data frame?
几天前我 post 提出了这个问题,但有人告诉我我的描述太混乱了。然而,在澄清了我的问题并添加了一个例子之后,这个问题没有得到任何进一步的关注。因为我仍然需要一个解决方案,所以我删除了旧问题,现在 post 它有希望以更好的形式出现。
下面的例子说明了我的问题。
我有两个对象。首先是一个数据框,描述每个人的 (id) 组 (group),s(he) 采取行动的年份 ( do.year) 和变量值 (var) 对于 2010 年和 2015 年之间的每一年 (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) 并从该值中减去组平均值 (var in 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 解决方案。
如果您想要 data.table
解决方案,这里有一个可能的解决方案。我建议首先将您的列表转换为带有 group
列的 data.table
。只需在 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
几天前我 post 提出了这个问题,但有人告诉我我的描述太混乱了。然而,在澄清了我的问题并添加了一个例子之后,这个问题没有得到任何进一步的关注。因为我仍然需要一个解决方案,所以我删除了旧问题,现在 post 它有希望以更好的形式出现。
下面的例子说明了我的问题。
我有两个对象。首先是一个数据框,描述每个人的 (id) 组 (group),s(he) 采取行动的年份 ( do.year) 和变量值 (var) 对于 2010 年和 2015 年之间的每一年 (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) 并从该值中减去组平均值 (var in 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 解决方案。
如果您想要 data.table
解决方案,这里有一个可能的解决方案。我建议首先将您的列表转换为带有 group
列的 data.table
。只需在 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