按列AND行合并数据框

时间:2013-12-19 04:39:42

标签: r merge row

我有两个共享相似方面的数据集,例如数据集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.如果没有匹配,我希望incomeNA

到目前为止,我试过

which(A$year==B$year & A$region==rownames(B)[2:6])

但我认为这不起作用。

我还想补充说,所有数据点都没有匹配,数据集A中的区域变量有NA,而数据集B中的年数不包括所有年份数据集A.

4 个答案:

答案 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 = TRUEmerge

答案 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的答案中的数据。)