R 按列和行合并数据帧

R 按列和行合并数据帧,r,merge,row,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

我有一个共享相似方面的两个数据集,例如数据集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列合并第二个数据集中的数字。例如,由于1980年鲍勃在第5区,相应的
收入将为140。如果没有匹配项,我希望
income
成为
NA

到目前为止我试过了

which(A$year==B$year & A$region==rownames(B)[2:6])
但我认为这不管用


我还想补充的是,并非所有数据点都匹配,数据集A中的区域变量都有NAs,数据集B中的年数并不涵盖数据集A中的所有年份。

您只需要将第二个数据集的格式从宽格式转换为长格式。使用重塑2plyr可以非常轻松地完成此操作:

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)
library(重塑2)
图书馆(plyr)

b您只需要将第二个数据集从宽格式转换为长格式。使用重塑2plyr可以非常轻松地完成此操作:

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)
library(重塑2)
图书馆(plyr)

这是另一种选择,因为乔兰让我工作

创建收入的
矩阵

b <- as.matrix(B[-1])
rownames(b) <- B[,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$income这里有一个替代方案,因为Joran让我工作

创建收入的
矩阵

b <- as.matrix(B[-1])
rownames(b) <- B[,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$income既然joran和Ananda选择了所有好的选择,这里有一个荒谬的选择:

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

a$income既然joran和Ananda选择了所有好的选择,这里有一个荒谬的选择:

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

a$income这是我在过去几周内第三次尝试为数据转换问题提供
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,因为在包下运行的数据库引擎强制使用非整数字段名

这是我在过去几周内第三次尝试为数据转换问题提供
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,因为在包下运行的数据库引擎强制使用非整数字段名

你能不能再详细说明一下熔体的作用以及“变量”=“区域”的含义?我尝试了melt命令,但它没有改变任何东西。@Rusuer9000,
melt
将数据转换为“长”形式
“variable”=“region”
只需将当您将
数据.帧
融化为“region”时创建的“variable”变量重命名为“region”。Joran,您可以通过使用
melt
中的
variable.name
参数
melt(b,id.vars=“year”,variable.name=“region”)来避免仅为
重命名而加载包
。您能否详细说明一下melt的作用以及“变量”=“区域”的含义?我尝试了melt命令,但它没有改变任何东西。@Rusuer9000,
melt
将数据转换为“长”形式
“variable”=“region”
只需将当您将
数据.帧
融化为“region”时创建的“variable”变量重命名为“region”。Joran,您可以通过使用
melt
中的
variable.name
参数
melt(b,id.vars=“year”,variable.name=“region”)来避免仅为
重命名而加载包
。我想你是在使用我的答案和@joran的答案中的数据,但是+1:-)我的观点是,当你的
mapply
指的是
a/b
时,你把它分配给了一个名为
a
的对象……哦,积垢球。。。你必须对我更明确一点——这是漫长的一年!;-)您好,我对我的问题进行了一些编辑-我认为在执行cbind?@Rusuer9000之后,当存在NAs时,该代码不起作用-joran的答案将适用于NA值。我的,不太多。我想你使用的是我的答案和@joran的答案中的数据,但是+1:-)我的观点是,当你的
mapply
指的是
a/b
,你把它分配给了一个名为
a
的对象……哦,积垢球。。。你必须对我更明确一点——这是漫长的一年!;-)您好,我对我的问题进行了一些编辑-我认为在执行cbind?@Rusuer9000之后,当存在NAs时,该代码不起作用-joran的答案将适用于NA值。我的,没那么多。非常感谢你的代码!但我有一个问题——因为不是所有的数据点都匹配,所以在我对整个数据集执行cbind(匹配(A$year,rownames(b)),A$region)之后,会有很多NAs,当我尝试从b中提取时,会出现一个错误“下标超出范围”。有没有办法提取我找到的答案,但将其余部分保留为NAs?@Rusuer9000,即使你编辑了我的答案和Joran的作品。您是否可以重新创建一个小数据集(以可复制的方式,就像我们在这些答案中所做的那样)来演示问题/错误?谢谢。我解决了这个问题——在进行cbind之后的矩阵是一个字符矩阵,在从b中提取之前,我必须将其转换为数字。非常感谢。非常感谢这段代码!但我有一个问题——因为不是所有的数据点都匹配,所以在我对整个数据集执行cbind(匹配(A$year,rownames(b)),A$region)之后,会有很多NAs,当我尝试从b中提取时,会出现一个错误“下标超出范围”。会有一个w吗