【问题标题】:repeat dataframe n times whilst adding column在添加列的同时重复数据帧 n 次
【发布时间】:2018-12-11 00:35:20
【问题描述】:

这是我的可重现代码:

df <- data.frame(x = c(1, 2), y = c(3, 4))

df1 <- df %>% mutate(z = 1)
df2 <- df %>% mutate(z = 2)
df3 <- df %>% mutate(z = 3)

df <- rbind(df1, df2, df3)

df

我将原始数据框 df 重复 3 次,同时添加一列,其中列中的数字表示重复。在我的用例中,我必须这样做超过 3 次。我可以使用循环,但有没有更简洁的方法?我想我不能使用 expand.grid。

【问题讨论】:

  • cbind(df, z = rep(1:n, each = nrow(df))) 其中n 是您想要的重复次数。
  • @qdread 这通常不起作用,因为cbind 转换为矩阵,而不是 data.frame
  • @CoreyLevinson 我认为cbind 有一个data.frame 方法,所以它应该可以工作。
  • @CoreyLevinson 只要你从一个数据框开始,cbind 就会给你一个数据框。 class(cbind(mtcars, 1)).

标签: r


【解决方案1】:

您也可以使用merge

dfz <- data.frame(z = 1:3)

merge(df, dfz)

#   x y z
# 1 1 3 1
# 2 2 4 1
# 3 1 3 2
# 4 2 4 2
# 5 1 3 3
# 6 2 4 3

【讨论】:

    【解决方案2】:

    我们可以创建一个list 列和unnest

    library(tidyverse)
    df %>%
       mutate(z = list(1:3)) %>%
       unnest %>%
       arrange(z)
    #  x y z
    #1 1 3 1
    #2 2 4 1
    #3 1 3 2
    #4 2 4 2
    #5 1 3 3
    #6 2 4 3
    

    【讨论】:

    • 另一个 z 是 df-counter 的成语:dplyr::bind_rows(rep(list(df), 3), .id="z")
    • @Frank 谢谢,我首先想到的是bind_rows 方式
    【解决方案3】:

    我们还可以使用sqldf 进行交叉连接。这将创建 dfreps 表的笛卡尔积:

    library(sqldf)
    reps <- data.frame(z = 1:3)
    
    sqldf("select * from df, reps order by z")
    

    或者简单地使用来自purrrmap_dfr

    library(purrr)
    
    map_dfr(1:3, ~cbind(df, z = .))
    

    输出:

      x y z
    1 1 3 1
    2 2 4 1
    3 1 3 2
    4 2 4 2
    5 1 3 3
    6 2 4 3
    

    【讨论】:

    • 哈哈,这对于像我这样的 sql 恐龙来说是另一种选择
    【解决方案4】:

    另一个使用base R的选项

    n <- 3
    do.call(rbind, 
            Map(`[<-`, replicate(n = n, 
                                 expr = df, 
                                 simplify = FALSE), 
                "z", 
                value = seq_len(n)))
    #  x y z
    #1 1 3 1
    #2 2 4 1
    #3 1 3 2
    #4 2 4 2
    #5 1 3 3
    #6 2 4 3
    

    【讨论】:

      【解决方案5】:

      其他一些尚未涉及的方法:

      # setup
      df = data.frame(x = c(1, 2), y = c(3, 4))
      n = 3
      
      # simple row indexing, add column manually
      result = df[rep(1:nrow(df), 3), ]
      result$id = rep(1:n, each = nrow(df))
      
      # cross join in base
      merge(df, data.frame(id = 1:n), by = NULL)
      
      # cross join in tidyr
      tidyr::crossing(df, data.frame(id = 1:n))
      
      # dplyr version of the row-index method above
      slice(df, rep(1:n(), n)) %>% mutate(id = rep(1:n, each = nrow(df)))
      

      灵感主要来自我的一个老问题How can I repeat a data frame?。基本上相同的问题,但没有id 列要求。

      【讨论】:

        猜你喜欢
        • 2019-02-23
        • 2021-09-19
        • 1970-01-01
        • 2020-10-07
        • 1970-01-01
        • 2019-05-09
        • 1970-01-01
        • 1970-01-01
        • 2019-02-10
        相关资源
        最近更新 更多