【问题标题】:Append a data frame to a master data frame if some columns are common [duplicate]如果某些列是常见的,则将数据框附加到主数据框[重复]
【发布时间】:2016-03-20 12:50:55
【问题描述】:

我想将一个数据帧附加到另一个数据帧(主数据帧)。问题是它们的列中只有一个子集是常见的。此外,它们的列顺序可能不同。

主数据框:

   a b  c
r1 1 2 -2
r2 2 4 -4
r3 3 6 -6
r4 4 8 -8

新数据框:

      d  a   c
r1 -120 10 -20
r2 -140 20 -40

预期结果:

    a   b    c
r1  1   2   -2
r2  2   4   -4
r3  3   6   -6
r4  4   8   -8
r5 10 NaN  -20
r6 20 NaN  -40

有什么聪明的方法吗? This 是一个类似的问题,但设置不同。

【问题讨论】:

    标签: r merge dataframe append


    【解决方案1】:

    查看dplyr 包中的bind_rows 函数。默认情况下,它会为您做一些好事,例如用NAs 填充存在于一个data.frame 但另一个不存在的列,而不是仅仅失败。这是一个例子:

    # Use the dplyr package for binding rows and for selecting columns
    library(dplyr)
    
    # Generate some example data
    a <- data.frame(a = rnorm(10), b = rnorm(10))
    b <- data.frame(a = rnorm(5), c = rnorm(5))
    
    # Stack data frames
    bind_rows(a, b)
    
    Source: local data frame [15 x 3]
    
                a          b          c
    1   2.2891895  0.1940835         NA
    2   0.7620825 -0.2441634         NA
    3   1.8289665  1.5280338         NA
    4  -0.9851729 -0.7187585         NA
    5   1.5829853  1.6609695         NA
    6   0.9231296  1.8052112         NA
    7  -0.5801230 -0.6928449         NA
    8   0.2033514 -0.6673596         NA
    9  -0.8576628  0.5163021         NA
    10  0.6296633 -1.2445280         NA
    11  2.1693068         NA -0.2556584
    12 -0.1048966         NA -0.3132198
    13  0.2673514         NA -1.1181995
    14  1.0937759         NA -2.5750115
    15 -0.8147180         NA -1.5525338
    

    要解决您的问题中的问题,您需要先选择主data.frame 中的列。如果a 是主data.frame,并且b 包含您要添加的数据,您可以使用dplyr 中的select 函数首先获取您需要的列。

    # Select all columns in b with the same names as in master data, a
    # Use select_() instead of select() to do standard evaluation.
    b <- select_(b, names(a))
    
    # Combine
    bind_rows(a, b)
    
    Source: local data frame [15 x 2]
    
                a          b
    1   2.2891895  0.1940835
    2   0.7620825 -0.2441634
    3   1.8289665  1.5280338
    4  -0.9851729 -0.7187585
    5   1.5829853  1.6609695
    6   0.9231296  1.8052112
    7  -0.5801230 -0.6928449
    8   0.2033514 -0.6673596
    9  -0.8576628  0.5163021
    10  0.6296633 -1.2445280
    11  2.1693068         NA
    12 -0.1048966         NA
    13  0.2673514         NA
    14  1.0937759         NA
    15 -0.8147180         NA
    

    【讨论】:

    • 我使用 R 版本 3.4.4,发现 select_() 已弃用。正常select() 不会产生想要的结果。
    • @vtenhunen 自从我的答案发布以来,dplyr api 发生了变化。您可以查看详细信息here。简而言之,不要使用select_(),而是尝试使用select(..., !! var),其中var 是一个包含列名的变量。
    【解决方案2】:

    试试这个:

    library(plyr) # thanks to comment @ialm
    df <- data.frame(a=1:4,b=seq(2,8,2),c=seq(-2,-8,-2))
    new <- data.frame(d=c(-120,-140),a=c(10,20),c=c(-20,40))
    
    # we use %in% to pull the columns that are the same in the master
    # then we use rbind.fill to put in this dataframe below the master
    # filling any missing data with NA values
    res <- rbind.fill(df,new[,colnames(new) %in% colnames(df)])
    
    > res
       a  b   c
    1  1  2  -2
    2  2  4  -4
    3  3  6  -6
    4  4  8  -8
    5 10 NA -20
    6 20 NA  40
    

    【讨论】:

      【解决方案3】:

      此处发布的基于 dplyr- 和 plyr 的解决方案对于此任务来说非常自然,分别使用 bind_rowsrbind.fill,尽管它也可以作为基础 R 中的单线。基本上我将遍历第一个数据帧的名称,如果存在第二个数据帧的对应列,则抓取它,否则返回所有 NaN 值。

      rbind(A, sapply(names(A), function(x) if (x %in% names(B)) B[,x] else rep(NaN, nrow(B))))
      #     a   b   c
      # r1  1   2  -2
      # r2  2   4  -4
      # r3  3   6  -6
      # r4  4   8  -8
      # 5  10 NaN -20
      # 6  20 NaN -40
      

      【讨论】:

        【解决方案4】:

        另一种选择是使用 plyr 包中的 rbind.fill

        引入您的示例数据

        toread <- "
        a b  c
        1 2 -2
        2 4 -4
        3 6 -6
        4 8 -8"
        master <- read.table(textConnection(toread), header = TRUE) 
        toread <- "
        d  a   c
        -120 10 -20
        -140 20 -40"
        to.append <- read.table(textConnection(toread), header = TRUE) 
        

        绑定数据

        library(plyr)
        rbind.fill(master, to.append)
        

        【讨论】:

        • 如果您使用的是dplyr,为什么不直接使用bind_rows()
        • @ialm 仔细阅读后,这个答案使用任何dplyr 函数(它只是加载包)。值得注意的是,加载plyr 之后加载dplyr 将使用plyr 版本掩盖dplyr::summarizedplyr::mutate,因此不推荐。
        • @Gregor 是的,我现在明白了。由于您在评论中强调的原因,如果您在 dplyr 之后加载 plyr 会发出警告,我相信如果您需要同时使用这两个软件包,Hadley 建议在 dplyr 之前加载 plyr。跨度>
        • 我不打算在答案中包含 dplyr 并且我将其删除。感谢您指出它不需要
        猜你喜欢
        • 2016-07-18
        • 1970-01-01
        • 2021-09-24
        • 2023-03-08
        • 2019-05-19
        • 2017-10-17
        • 2016-10-01
        • 2020-05-05
        • 1970-01-01
        相关资源
        最近更新 更多