【问题标题】:Alternative to expand.grid for data.frames用于 data.frames 的 expand.grid 的替代方案
【发布时间】:2012-07-27 18:27:35
【问题描述】:

我有一个data.frame df,我希望df 中的每一行都重复lengthTime 次,并添加一个从1 到lengthTime 的新列,用于@987654325 中的每一行@。

我知道,这听起来很复杂,但我基本上想要将expand.grid 应用于df。这是一个丑陋的解决方法,我觉得最简单的解决方案(甚至可能是 base-R 函数?):

df <- data.frame(ID   = rep(letters[1:3], each=3),
                 CatA = rep(1:3, times = 3),
                 CatB = letters[1:9])
lengthTime <- 3
nrRow <- nrow(df)
intDF <- df
for (i in 1:(lengthTime - 1)) {
  df <- rbind(df, intDF)
}
df$Time <- rep(1:lengthTime, each=nrRow)

我以为我可以只使用expand.grid(df, 1:lengthTime),但这不起作用。 outer 也没有带来任何运气。那么有人知道一个好的解决方案吗?

【问题讨论】:

    标签: r


    【解决方案1】:

    这个问题发布已经有一段时间了,但我最近发现它只是在寻找标题中的内容,即适用于数据帧的expand.grid。发布的答案解决了 OP 更具体的问题,所以如果有人正在寻找更通用的数据帧解决方案,这里有一个更通用的方法:

    expand.grid.df <- function(...) Reduce(function(...) merge(..., by=NULL), list(...))
    
    # For the example in the OP
    expand.grid.df(df, data.frame(1:lengthTime))
    
    # More generally
    df1 <- data.frame(A=1:3, B=11:13)
    df2 <- data.frame(C=51:52, D=c("Y", "N"))
    df3 <- data.frame(E=c("+", "-"))
    expand.grid.df(df1, df2, df3)
    

    【讨论】:

    • 工作得非常好......我在this SO post 中使用了这种方法,在我的解决方案中:SO link
    【解决方案2】:

    为什么不用df[rep(1:nrow(df),times = 3),] 之类的东西来扩展数据框,然后像上面一样添加额外的列,使用df$Time &lt;- rep(1:lengthTime, each=nrRow)

    【讨论】:

      【解决方案3】:

      您也可以通过NULL 执行简单的merge(这将导致merge 进行简单的组合数据复制):

      merge(data.frame(time=1:lengthTime), iris, by=NULL)
      

      【讨论】:

      • 我最喜欢这个解决方案,但为了简单起见(避免依赖),你可以写merge(data.frame(time=1:lengthTime), iris, by=NULL)
      【解决方案4】:

      快速更新

      现在在包 tidyr 中还有 cross() 函数,可以用来代替合并,速度更快,并且返回一个 tbl_df / tibble。

      data.frame(time=1:10) %>% merge(iris, by=NULL) 
      
      data.frame(time=1:10) %>% tidyr::crossing(iris) 
      

      【讨论】:

        【解决方案5】:

        这行得通:

        REP <- rep(1:nrow(df), 3)
        df2 <- data.frame(df[REP, ], Time = rep(1:3, each = 9))
        rownames(df2) <- NULL
        df2
        

        【讨论】:

        • 我的确实与 joran 的没有什么不同,后者在几秒钟内击败了我 40 秒,但我会留下它,因为它稍微更明确一些。
        • 先到先得,所以我接受了他的回答 ;-) 但是你们俩都是 +1。这是一个非常巧妙的解决方案!
        【解决方案6】:

        data.table 解决方案:

        > library(data.table)
        >  ( df <- data.frame(ID   = rep(letters[1:3], each=3),
        +                  CatA = rep(1:3, times = 3),
        +                  CatB = letters[1:9]) )
          ID CatA CatB
        1  a    1    a
        2  a    2    b
        3  a    3    c
        4  b    1    d
        5  b    2    e
        6  b    3    f
        7  c    1    g
        8  c    2    h
        9  c    3    i
        > ( DT <- data.table(df)[, lapply(.SD, function(x) rep(x,3))][, Time:=rep(1:3, each=nrow(df0))] )
            ID CatA CatB Time
         1:  a    1    a    1
         2:  a    2    b    1
         3:  a    3    c    1
         4:  b    1    d    1
         5:  b    2    e    1
         6:  b    3    f    1
         7:  c    1    g    1
         8:  c    2    h    1
         9:  c    3    i    1
        10:  a    1    a    2
        11:  a    2    b    2
        12:  a    3    c    2
        13:  b    1    d    2
        14:  b    2    e    2
        15:  b    3    f    2
        16:  c    1    g    2
        17:  c    2    h    2
        18:  c    3    i    2
        19:  a    1    a    3
        20:  a    2    b    3
        21:  a    3    c    3
        22:  b    1    d    3
        23:  b    2    e    3
        24:  b    3    f    3
        25:  c    1    g    3
        26:  c    2    h    3
        27:  c    3    i    3
        

        另一个:

        > library(data.table)
        >  ( df <- data.frame(ID   = rep(letters[1:3], each=3),
        +                  CatA = rep(1:3, times = 3),
        +                  CatB = letters[1:9]) )
        > DT <- data.table(df)
        > rbindlist(lapply(1:3, function(i) cbind(DT, Time=i)))
            ID CatA CatB Time
         1:  a    1    a    1
         2:  a    2    b    1
         3:  a    3    c    1
         4:  b    1    d    1
         5:  b    2    e    1
         6:  b    3    f    1
         7:  c    1    g    1
         8:  c    2    h    1
         9:  c    3    i    1
        10:  a    1    a    2
        11:  a    2    b    2
        12:  a    3    c    2
        13:  b    1    d    2
        14:  b    2    e    2
        15:  b    3    f    2
        16:  c    1    g    2
        17:  c    2    h    2
        18:  c    3    i    2
        19:  a    1    a    3
        20:  a    2    b    3
        21:  a    3    c    3
        22:  b    1    d    3
        23:  b    2    e    3
        24:  b    3    f    3
        25:  c    1    g    3
        26:  c    2    h    3
        27:  c    3    i    3
        

        【讨论】:

          猜你喜欢
          • 2015-05-04
          • 2015-07-17
          • 2022-07-25
          • 2011-06-29
          • 2015-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-10
          相关资源
          最近更新 更多