在R中合并数据

4

我有一个数据集A

paper_id author_id
  1       521630
  1       1611750
  2       9
  3       627950
  4       1456512
  8       15
  ........

和数据集B

author_id    author_name        author_affiliation
    9       Ernest Jordan            Cambridge                                                    
    14         K. MORIBE               NA                                                 
    15     D. Jakominich               NA                                                 
    25     William H. Nailon                                                                
    37     P. B. Littlewood    Cavendish Laboratory|Cambridge University 
    ........       

我希望能够通过作者ID将这两个数据集合并,但结果应该呈现为以下形式:
paper id    author_id        author_name     author_affiliation
  2            9             Ernest Jordan     Cambridge
  8            15            D. Jakominich       NA

我希望只按照paper_id的顺序呈现数据并在author_id上进行合并,使得所有paper_id的顺序不会被打乱。

我所做的是:

b<-merge(A,B,by="author_id")

我正在遇到问题。在这种情况下,paper_id被干扰了。

 author_id paper_id       author_name      author_affiliation
     9     1468598       Ernest Jordan       cambridge
     9     1682105       Ernest Jordan       cambridge

然后我必须通过浏览paper_id列来对此输出进行排序。这是一种非常低效的方法。

有什么更好的方法吗?

谢谢。


什么是低效的?在合并后对数据进行排序吗?我不确定您对当前输出的问题是什么。 - rawr
2
您可以重新排序数据:b[order(b$paper_id), ] - jbaums
好的,谢谢。我只是想知道是否有更好的方法。 - user3171906
我没有看到(下面)你需要重新排序结果。请澄清你的问题。 - gung - Reinstate Monica
您可以在 merge 函数中指定参数 sort=FALSE,这样合并后的数据将不会根据 by 列进行排序。但是,行将以“未指定的顺序”排列。有关更多上下文信息,请参阅 merge 的帮助页面中的 Value 部分。 - Brian Diggs
3个回答

2
这应该可以满足你的要求。
b <-merge(A,B,by="author_id", sort=F)
b <- b[,c(2,1,3,4)]

您可以使用sort=F关闭by=...列的排序,但merge(...)总是会将排序列作为结果的第一列。最后一行代码只是颠倒了第1列和第2列。 编辑(回应@BrianDiggs评论)
@BrianDiggs正确指出,尽管sort=F不会强制对A中的by=...列进行排序,但它并不保证原始排序顺序。如果效率是一个重要考虑因素,则可以考虑使用data.table包,该包专门用于此目的。
# create an example
A <- data.frame(paper_id=1:10000, author_id=rev(LETTERS[1:4]))
B <- data.frame(author_id=LETTERS[1:4],
                author_name=c("Davies","Hawking","Carlyle","Higgs"),
                author_affiliation=c("Oxford","Cambridge","UCL","Edinburgh"),
                stringsAsFactors=F)

library(data.table)
A <- data.table(A,key="author_id")
B <- data.table(B,key="author_id")
A[B,c("author_name","author_affiliation"):=list(author_name,author_affiliation)]
setkey(A,paper_id)
head(A)
#    paper_id author_id author_name author_affiliation
# 1:        1         D       Higgs          Edinburgh
# 2:        2         C     Carlyle                UCL
# 3:        3         B     Hawking          Cambridge
# 4:        4         A      Davies             Oxford
# 5:        5         D       Higgs          Edinburgh
# 6:        6         C     Carlyle                UCL

sort(...)不同,设置数据表中的键会使用基数算法“按引用”排序。按引用排序意味着行在内存中重新排列,而不是将整个表复制到新表中。因此,数据表的排序非常快速和内存高效。

此外,使用A[B,...]进行合并比合并两个数据框架要快得多。此外,此过程将新列附加到A(而不是像merge(...)一样创建A的副本)。


请注意,sort=FALSE不能保证b的顺序与A(或B)相同;文档中说明了顺序是未指定的。因此,您仍需要使用b<-b[order(b$paper_id),]来确保排序。 - Brian Diggs
@BrianDiggs - 你说得对。不过在楼主的情况下似乎是有效的。请看修改记录。 - jlhoward

1
如果您可以考虑非base替代方案,那么您可以尝试plyrjoin等价物来替代merge。从?join中的"Details"得知:与merge不同,无论使用何种连接类型,都会保留x的顺序。列的顺序也被保留。
library(plyr)
join(A, B, type = "inner")
# Joining by: author_id
#   paper_id author_id  author_name author_affiliation
# 1        2         9 ErnestJordan          Cambridge
# 2        8        15   Jakominich               <NA>

dplyr 中的 inner_join 和它很相似。但是,虽然保留了 x 中列的顺序,但是 y 中的列似乎按字母顺序排序:

library(dplyr)
inner_join(x = A, y = B)
# Joining by: "author_id"
#   paper_id author_id author_affiliation  author_name
# 1        2         9          Cambridge ErnestJordan
# 2        8        15               <NA>   Jakominich

0

太长了,不适合作为评论。

我明白你想要什么:

A <- read.table(text="paper_id author_id
1       521630
1       1611750
2       9
3       627950
4       1456512
8       15", header=T)

B <- read.table(text="author_id  author_name author_affiliation
9       Ernest_Jordan            Cambridge
14         K._MORIBE               NA
15     D._Jakominich               NA
25     William_H._Nailon           NA
37     P._B._Littlewood    Cavendish_Laboratory|Cambridge_University", 
header=T)

b <- merge(A, B, by="author_id")
b
#   author_id paper_id   author_name author_affiliation
# 1         9        2 Ernest_Jordan          Cambridge
# 2        15        8 D._Jakominich               <NA>

你能澄清一下你的问题吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接