首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >连接2个数据集并创建匹配的新行

连接2个数据集并创建匹配的新行
EN

Stack Overflow用户
提问于 2016-08-03 18:50:35
回答 7查看 173关注 0票数 6

我有两个数据集我想加入使用R-

数据集1

代码语言:javascript
复制
    ID Name Date Price
    1    A   2011 $100
    2    B   2012 $200
    3    C   2013 $300

数据集2

代码语言:javascript
复制
    ID Date Price
    1  2012 $100
    1  2013 $200
    3  2014 $300

通过ID在left-join()中使用dplyr,我最终会得到以下结果

代码语言:javascript
复制
    ID Name Date.x Price.x Date.y Price.y
    1   A   2011    $100   2012   $100
    1   A   2011    $100   2013   $200
    2   B   2012    $200
    3   C   2013    $300   2014   $300

然而,作为最终产品,我想要的是

代码语言:javascript
复制
    ID Name Date Price
    1  A     2011 $100
    1  A     2012 $100
    1  A     2013 $200
    2  B     2012 $200
    3  C     2013 $300
    3  C     2014 $300

也就是说,我不想合并到现有的行,而是在找到匹配时创建一个新行,并复制现有的不会更改的信息(ID和名称),并在必要时更改Date和Price列。对于如何在大型数据集上有效地执行此操作,有什么想法吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2016-08-03 19:02:50

您询问了有效的方法,所以我将介绍data.table:

代码语言:javascript
复制
library(data.table)
setDT(DF1)
setDT(DF2)

# structure your data so ID attributes are only in an ID table
idDT = DF1[, .(ID, Name)]
DF1[, Name := NULL]

# stack data
DT = rbind(DF1, DF2)

# grab ID attributes if you really need them
DT[idDT, on="ID", Name := i.Name]

这给

代码语言:javascript
复制
   ID Date Price Name
1:  1 2011  $100    A
2:  2 2012  $200    B
3:  3 2013  $300    C
4:  1 2012  $100    A
5:  1 2013  $200    A
6:  3 2014  $300    C

rbind for data.tables是相当快的。不过,当只绑定两个表时,我并不认为效率会成为一个大问题。

关于剥离ID属性Name,它与dplyr的建议相匹配,后者将其称为making data tidy

票数 6
EN

Stack Overflow用户

发布于 2016-08-03 19:58:48

这与弗兰克的回答略有不同。主要问题是您的第二个表没有Name列。使用data.table的update而连接方法可以非常有效地获得这一结果。

代码语言:javascript
复制
require(data.table)
dt2[dt1, Name := i.Name, on = "ID"] # by reference, no need to assign the result back

现在有了一个Name列,我们可以简单地rbind结果。

代码语言:javascript
复制
ans = rbind(dt1, if (anyNA(dt2$Name)) na.omit(dt2, by="Name") else dt2)

如果有必要,使用setorder()通过引用重新排序结果

代码语言:javascript
复制
setorder(ans, ID, Name) # by reference, no need to assign the result back
#    ID Name Date Price
# 1:  1    A 2011  $100
# 2:  1    A 2012  $100
# 3:  1    A 2013  $200
# 4:  2    B 2012  $200
# 5:  3    C 2013  $300
# 6:  3    C 2014  $300

:=操作符和set*函数在data.table中通过引用修改输入对象。

代码语言:javascript
复制
dt1 = fread('ID Name   Date Price
              1    A   2011  $100
              2    B   2012  $200
              3    C   2013  $300')

dt2 = fread('ID  Date Price
              1  2012  $100
              1  2013  $200
              3  2014  $300')
票数 4
EN

Stack Overflow用户

发布于 2016-08-03 19:05:30

代码语言:javascript
复制
df1 <- data.frame(
  ID=1:3,
  Name=c("A","B","C"),
  Date=c(2011,2012,2013),
  Price=c(100,200,300)
)

df2 <- data.frame(
  ID=c(1,1,3),
  Date=c(2012,2013,2014),
  Price=c(100,200,300)
)

left_join不会给您提供所需的输出。您可以使用full_join

代码语言:javascript
复制
merged <- full_join(df1, df2, by=c("Date","ID"))

下面是使用meltreshape2包获得所需输出的一种方法:

代码语言:javascript
复制
library(reshape2)
merged <- melt(merged, id.vars=c("ID","Name","Date"))

然后:

代码语言:javascript
复制
> merged[na.omit(merged$Name), -4] #remove NAs and column from melt
    ID Name Date value
1    1    A 2011   100
2    2    B 2012   200
3    3    C 2013   300
1.1  1    A 2011   100
2.1  2    B 2012   200
3.1  3    C 2013   300
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38751486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档