我正在尝试将两个数据帧的合并循环到多个列上,但是我遇到了代码问题并且无法在SO上找到任何答案。以下是一些示例数据框:
box <- c(5,7,2)
year <- c(1999,1999,1999)
rep5 <- c(5,5,5)
rep7 <- c(7,7,7)
rep2 <- c(2,2,2)
df1 <- data.frame(box,year,rep5,rep7,rep2)
box1 <- c(5,5,5,5,7,7,7,7,2,2,2,2)
box2 <- c(5,7,2,5,5,7,2,4,5,7,2,9)
year2 <- c(1999,1999,1999,2000,1999,1999,1999,1999,1999,1999,1999,1999)
distance <- c(0,100,200,0,100,0,300,200,200,300,0,300)
df2 <- data.frame(box1,box2,year2,distance)
df1
box year rep5 rep7 rep2
1 5 1999 5 7 2
2 7 1999 5 7 2
3 2 1999 5 7 2
df2
box1 box2 year2 distance
1 5 5 1999 0
2 5 7 1999 100
3 5 2 1999 200
4 5 5 2000 0
5 7 5 1999 100
6 7 7 1999 0
7 7 2 1999 300
8 7 4 1999 200
9 2 5 1999 200
10 2 7 1999 300
11 2 2 1999 0
12 2 9 1999 300
我要做的是从df2获取距离信息到df1,df1年与df2年匹配,df1框与df2 box1匹配,df1 rep [i]与df2 box2匹配。我可以为单个df1 rep [i]列执行此操作,如下所示:
merge(df1, df2, by.x=c("box", "rep5", "year"), by.y=c("box1", "box2", "year2"), all.x = TRUE)
这给出了所需的输出:
box rep5 year rep7 rep2 distance
1 2 5 1999 7 2 200
2 5 5 1999 7 2 0
3 7 5 1999 7 2 100
但是,为了保存每个rep [i]列单独执行此操作(我在实际数据集中有很多这些列),我希望能够遍历这些列。这是我试图做的代码:
reps <- c(df1$rep7, df1$rep2)
df3 <- for (i in reps) {merge(df1, df2, by.x=c("box", i, "year"), by.y=c("box1", "box2", "year2"), all.x = TRUE)}
df3
当我运行该代码时,我在fix.by(by.x,x)中收到错误&#34;错误:&#39; by&#39;必须指定唯一有效的列。&#34;我也尝试过定义
reps <- c("rep7", "rep2")
当我使用该定义运行相同的代码时,我得到df3为NULL的结果。
我想要的输出(为了清晰起见重命名了距离列)是:
box year rep5 rep7 rep2 dist5 dist7 dist2
1 2 1999 5 7 2 200 300 0
2 5 1999 5 7 2 0 100 200
3 7 1999 5 7 2 100 0 300
我做错了什么?非常感谢您给我的任何帮助!
答案 0 :(得分:4)
当我了解图书馆dplyr
和tidyr
以及concept of tidy data sets时,我的生活变得更加轻松。您在上面尝试执行的操作可以表示为pivot
,并且很容易使用dplyr
和tidyr
。
我假设你真正想要的是转df2:
box1 box2 year2 distance
1 5 5 1999 0
2 5 7 1999 100
3 5 2 1999 200
4 5 5 2000 0
5 7 5 1999 100
6 7 7 1999 0
7 7 2 1999 300
8 7 4 1999 200
9 2 5 1999 200
10 2 7 1999 300
11 2 2 1999 0
12 2 9 1999 300
进入你的输出,删除了所有那些奇怪的重复:
box year dist5 dist7 dist2
1 2 1999 200 300 0
2 5 1999 0 100 200
3 7 1999 100 0 300
因此,您应将box2
转换为列,并将距离作为值。使用dplyr
和tidyr
:
library(tidyr)
box1 <- c(5,5,5,5,7,7,7,7,2,2,2,2)
box2 <- c(5,7,2,5,5,7,2,4,5,7,2,9)
year2 <- c(1999,1999,1999,2000,1999,1999,1999,1999,1999,1999,1999,1999)
distance <- c(0,100,200,0,100,0,300,200,200,300,0,300)
df2 <- data.frame(box1,box2,year2,distance)
# reshape it as desired
spread(df2, box2, distance,fill=0)
#Source: local data frame [4 x 7]
# box1 year2 2 4 5 7 9
#1 2 1999 0 0 200 300 300
#2 5 1999 200 0 0 100 0
#3 5 2000 0 0 0 0 0
#4 7 1999 300 200 100 0 0
我的建议:学会使用dplyr
和tidyr
。它让生活如此轻松。