【问题标题】:merging two dataframes based on one column without duplicating rows and preserving more data基于一列合并两个数据框而不重复行并保留更多数据
【发布时间】:2018-10-05 18:57:33
【问题描述】:

我的目标是合并两个基于列genus 的大型数据框,但具有不重复行的特殊条件(第一次尝试未解决);并且还保留来自两个数据帧的更多信息(在第二次尝试中未解决),请查看所需的输出:

chromdata <- read.table(text="
 genus sp
1      Acosta       Acosta_1
2    Aguilera     Aguilera_1
3      Acosta       Acosta_2
4    Aguilera     Aguilera_2
5       other              1   # EDIT: new rows    
6       other              2",header=TRUE,fill=TRUE,stringsAsFactors=FALSE)

treedata <- read.table(text="
 genus sp
1      Acosta       Acosta_3
2    Aguilera     Aguilera_3
3      Acosta       Acosta_4
4    Aguilera     Aguilera_4
5       other              3",header=TRUE,fill=TRUE,stringsAsFactors=FALSE)

#First try
merge(chromdata,treedata, by="genus", all=F)

#Second try
chromdata$sp2<-treedata$sp[match(chromdata$genus, treedata$genus)]
chromdata
     genus         sp        sp2
1   Acosta   Acosta_1   Acosta_3
2 Aguilera Aguilera_1 Aguilera_3
3   Acosta   Acosta_2   Acosta_3 #Acosta_4 missing
4 Aguilera Aguilera_2 Aguilera_3 # Aguilera_4 missing
5    other          1          3
6    other          2          3 

期望的输出:

     genus         sp        sp2
1   Acosta   Acosta_1   Acosta_3
2 Aguilera Aguilera_1 Aguilera_3
3   Acosta   Acosta_2   Acosta_4
4 Aguilera Aguilera_2 Aguilera_4
5    other          1          3 # EDIT: new rows
6    other          2          3

【问题讨论】:

    标签: r dataframe merge


    【解决方案1】:

    您可以添加另一列进行合并:

    library(data.table)
    merge(
      transform(chromdata, r = rowid(genus)), 
      transform(treedata, r = rowid(genus)), 
      by=c("r", "genus")
    )
    
      r    genus       sp.x       sp.y
    1 1   Acosta   Acosta_1   Acosta_3
    2 1 Aguilera Aguilera_1 Aguilera_3
    3 2   Acosta   Acosta_2   Acosta_4
    4 2 Aguilera Aguilera_2 Aguilera_4
    

    如果你不想加载 data.table,你也可以得到类似 ave(genus, genus, FUN = seq_along)many other ways 的 rowid。

    【讨论】:

    • 我发现了一个答案不起作用的案例,请参阅编辑。
    • 解决了在你的函数中添加 , all.x=T) ;图书馆(tidyverse); df %>% group_by(genus) %>% fill(sp.y)
    【解决方案2】:

    我想详细说明 data.table 方法。

    首先,您可以读取数据,然后直接将其转换为 data.table 对象:

    library(data.table)
    
    chromdata <- as.data.table(read.table(text="
     genus sp
                            1      Acosta       Acosta_1
                            2    Aguilera     Aguilera_1
                            3      Acosta       Acosta_2
                            4    Aguilera     Aguilera_2",header=TRUE,fill=TRUE,stringsAsFactors=FALSE))
    
    treedata <- as.data.table(read.table(text="
                           genus sp
                           1      Acosta       Acosta_3
                           2    Aguilera     Aguilera_3
                           3      Acosta       Acosta_4
                           4    Aguilera     Aguilera_4",header=TRUE,fill=TRUE,stringsAsFactors=FALSE))
    

    之后,您需要一个额外的列来实现所需的输出所需的合并操作:

    chromdata[, N := seq_len(.N), genus]
    treedata[, N := seq_len(.N), genus]
    

    这些行为您提供组内的行 ID。

    最后,在 data.table 包的帮助下,我们可以在公共列上合并这两个表:

    chromdata[treedata, on = c("genus", "N")]
    

    最终输出:

          genus         sp N       i.sp
    1:   Acosta   Acosta_1 1   Acosta_3
    2: Aguilera Aguilera_1 1 Aguilera_3
    3:   Acosta   Acosta_2 2   Acosta_4
    4: Aguilera Aguilera_2 2 Aguilera_4
    

    【讨论】:

    • 这个类似于rowidv函数。
    • @Ferroao 我知道,正如我所说的,我想详细说明 data.table 视角
    • rowidv 也是 data.table
    猜你喜欢
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 2018-01-30
    • 2019-02-12
    • 2017-12-27
    • 2021-11-28
    • 2017-11-26
    • 1970-01-01
    相关资源
    最近更新 更多