【问题标题】:Change the form while merging multiple data frames合并多个数据框时更改表单
【发布时间】:2018-10-11 21:58:30
【问题描述】:

我有几个格式相同的数据框,例如:

price <- data.frame(Year= c(2001, 2002, 2003),
                    A=c(1,2,3),B=c(2,3,4), C=c(4,5,6))
size <- data.frame(Year= c(2001, 2002, 2003), 
                   A=c(1,2,3),B=c(2,3,4), C=c(4,5,6))
performance <- data.frame(Year= c(2001, 2002, 2003),
                          A=c(1,2,3),B=c(2,3,4), C=c(4,5,6))

> price
  Year A B C
1 2001 1 2 4
2 2002 2 3 5
3 2003 3 4 6

> size
  Year A B C
1 2001 1 2 4
2 2002 2 3 5
3 2003 3 4 6

> performance
  Year A B C
1 2001 1 2 4
2 2002 2 3 5
3 2003 3 4 6

我想合并这些数据帧,但结果形式不同,所需的输出如下:

> df
  name Year price size performance
1    A 2001     1    1           1
2    A 2002     2    2           2
3    A 2003     3    3           3
4    B 2001     2    2           2
5    B 2002     3    3           3
6    B 2003     4    4           4
7    C 2001     3    3           3
8    C 2002     4    4           4
9    C 2003     5    5           5

按名称顺序排列数据,然后是排序日期。由于我在 20 个数据框中的每个数据框中都有超过 2000 个名称和 180 个日期,因此仅通过输入特定名称来对其进行排序太困难了。

【问题讨论】:

    标签: r dataframe merge


    【解决方案1】:

    您需要将数据帧转换为长格式,然后将它们连接在一起

    library(tidyverse)
    
    price_long <- price %>% gather(key, value = "price", -Year)
    size_long <- size %>% gather(key, value = "size", -Year)
    performance_long <- performance %>% gather(key, value = "performance", -Year)
    
    price_long %>% 
      left_join(size_long) %>% 
      left_join(performance_long)
    
    Joining, by = c("Year", "key")
    Joining, by = c("Year", "key")
    
      Year key price size performance
    1 2001   A     1    1           1
    2 2002   A     2    2           2
    3 2003   A     3    3           3
    4 2001   B     2    2           2
    5 2002   B     3    3           3
    6 2003   B     4    4           4
    7 2001   C     4    4           4
    8 2002   C     5    5           5
    9 2003   C     6    6           6
    

    【讨论】:

      【解决方案2】:

      你可以使用data.table

      library(data.table)
      a=list(price=price,size=size,performance=performance)
      dcast(melt(rbindlist(a,T,idcol = "name"),1:2),variable+Year~name)
         variable Year performance price size
      1:        A 2001           1     1    1
      2:        A 2002           2     2    2
      3:        A 2003           3     3    3
      4:        B 2001           2     2    2
      5:        B 2002           3     3    3
      6:        B 2003           4     4    4
      7:        C 2001           4     4    4
      8:        C 2002           5     5    5
      9:        C 2003           6     6    6
      

      【讨论】:

        【解决方案3】:

        我们可以合并数据帧,收集和传播合并的数据帧。

        library(tidyverse)
        
        dat <- list(price, size, performance) %>%
          setNames(c("price", "size", "performance")) %>%
          bind_rows(.id = "type") %>%
          gather(name, value, A:C) %>%
          spread(type, value) %>%
          arrange(name, Year)
        
        dat
        #   Year name performance price size
        # 1 2001    A           1     1    1
        # 2 2002    A           2     2    2
        # 3 2003    A           3     3    3
        # 4 2001    B           2     2    2
        # 5 2002    B           3     3    3
        # 6 2003    B           4     4    4
        # 7 2001    C           4     4    4
        # 8 2002    C           5     5    5
        # 9 2003    C           6     6    6
        

        【讨论】:

        • 对不起。我没有意识到您已经添加了基于bind_rows 的答案。我会删除我的。也许,您可以使用bind_rows(list(price = price, size = size, performance = performance), .id="Type") 而不是使用setNames
        • @MKR 如何保留它,因为您的答案显示了每个功能的一些细微的不同用途?它可能很有价值。
        • 好的。谢谢。没问题。
        【解决方案4】:

        dplyr::bind_rows 在这种情况下非常方便。解决方案可以是:

        library(tidyverse)
        
        bind_rows(list(price = price, size = size, performance = performance), .id="Type") %>%
          gather(Key, Value, - Type, -Year) %>%
          spread(Type, Value)
        
        #   Year Key performance price size
        # 1 2001   A           1     1    1
        # 2 2001   B           2     2    2
        # 3 2001   C           4     4    4
        # 4 2002   A           2     2    2
        # 5 2002   B           3     3    3
        # 6 2002   C           5     5    5
        # 7 2003   A           3     3    3
        # 8 2003   B           4     4    4
        # 9 2003   C           6     6    6
        

        上述解决方案与@www 的解决方案非常相似。它只是避免使用setNames

        【讨论】:

          【解决方案5】:

          为了完善它,这里是无包的基本 R 答案。

          # gather the data.frames into a list
          myList <- mget(ls())
          

          请注意,这三个 data.frame 是我的环境中唯一的对象。

          # get the final data.frame
          Reduce(merge, 
                 Map(function(x, y) setNames(cbind(x[1], stack(x[-1])), c("Year", y, "ID")),
                     myList, names(myList)))
          

          返回

            Year ID performance price size
          1 2001  A           1     1    1
          2 2001  B           2     2    2
          3 2001  C           4     4    4
          4 2002  A           2     2    2
          5 2002  B           3     3    3
          6 2002  C           5     5    5
          7 2003  A           3     3    3
          8 2003  B           4     4    4
          9 2003  C           6     6    6
          

          【讨论】:

            猜你喜欢
            • 2017-03-21
            • 2020-06-11
            • 2020-04-15
            • 1970-01-01
            • 2021-11-18
            • 1970-01-01
            • 2015-04-17
            • 2013-06-04
            • 2018-03-09
            相关资源
            最近更新 更多