我有两个共享相似方面的数据集,例如数据集A
name year region
Jane 1980 1
Jane 1981 2
Mike 1980 1
Mike 1985 4
Bob 1980 NA
Bob 1981 1
和数据集B
year 1 2 3 4 5
1980 12 44 76 108 140
1981 55 77 99 121 143
1982 56 76 96 116 136
1983 56 43 30 17 4
我想在名为" income
"的第一个数据集中创建一个新列。它根据年份和第1-5列合并第二个数据集中的数字。例如,由于Bob在1980年位于区域5,相应的income
将为140.如果没有匹配,我希望income
为NA
。
到目前为止,我试过
which(A$year==B$year & A$region==rownames(B)[2:6])
但我认为这不起作用。
我还想补充说,所有数据点都没有匹配,数据集A中的区域变量有NA,而数据集B中的年数不包括所有年份数据集A.
答案 0 :(得分:3)
这是我在过去几周内为数据转换问题提供sqldf
解决方案的第三次尝试。没有爱。我们会看到这次人们的想法......
使用Joran回答的数据:
require(sqldf)
sqldf('select
a.name
,a.year
,a.region
,case
when region = 1 then b.X1
when region = 2 then b.X2
when region = 3 then b.X3
when region = 4 then b.X4
when region = 5 then b.X5
end income
from a
join b
on a.year= b.year')
这里我使用标准的SQL case语句“熔化”数据。
sqldf
确实要求b
中的区域列前缀为X作为在包强制非整数字段名称下运行的数据库引擎。
答案 1 :(得分:1)
您只需将第二个数据集从宽格式转换为长格式即可。使用 reshape2 和 plyr 可以轻松完成此操作:
library(reshape2)
library(plyr)
b <- read.table(text = "year 1 2 3 4 5
1980 12 44 76 108 140
1981 55 77 99 121 143
1982 56 76 96 116 136
1983 56 43 30 17 4",header = TRUE,sep = "",check.names = FALSE)
a <- read.table(text = "name year region
Jane 1980 1
Jane 1981 2
Mike 1980 1
Mike 1981 4
Bob 1980 5
Bob 1981 1",header = TRUE,sep = "")
b <- melt(b,id.vars = "year")
b <- rename(b,c("variable" = "region"))
merge(a,b,all.x = TRUE)
根据您想要的加入类型,您可以在all.y = TRUE
中使用all = TRUE
或merge
。
答案 2 :(得分:1)
这是Joran让我工作的另一种选择....
创建一个matrix
的收入。
b <- as.matrix(B[-1])
rownames(b) <- B[,1]
使用match
将第一个data.frame
中的“年”与此新矩阵的rownames
相匹配。我们可以创建一个矩阵,将其作为第一列(行索引)和原始data.frame
中的“区域”作为第二列(列索引)。
cbind(match(A$year, rownames(b)), A$region)
# [,1] [,2]
# [1,] 1 1
# [2,] 2 2
# [3,] 1 1
# [4,] 2 4
# [5,] 1 5
# [6,] 2 1
我们可以使用它从矩阵“b”中提取相关数据,并将其添加到原始data.frame
。
A$income <- b[cbind(match(A$year, rownames(b)), A$region)]
A
# name year region income
# 1 Jane 1980 1 12
# 2 Jane 1981 2 77
# 3 Mike 1980 1 12
# 4 Mike 1981 4 121
# 5 Bob 1980 5 140
# 6 Bob 1981 1 55
这假设我们开始于:
A <- read.table(text = "name year region
Jane 1980 1
Jane 1981 2
Mike 1980 1
Mike 1981 4
Bob 1980 5
Bob 1981 1",header = TRUE,sep = "")
B <- read.table(text = "year 1 2 3 4 5
1980 12 44 76 108 140
1981 55 77 99 121 143
1982 56 76 96 116 136
1983 56 43 30 17 4",header = TRUE,sep = "",check.names = FALSE)
答案 3 :(得分:1)
由于朱兰和阿南达正在采取所有好的选择,这是一个荒谬的选择:
a$income <-
mapply(function(ro,co) b[ro,co], match(a$year,b$year), as.character(a$region))
# name year region income
#1 Jane 1980 1 12
#2 Jane 1981 2 77
#3 Mike 1980 1 12
#4 Mike 1981 4 121
#5 Bob 1980 5 140
#6 Bob 1981 1 55
(这使用了joran的答案中的数据。)