Alternative to expand.grid for data.frames

前端 未结 6 1380
误落风尘
误落风尘 2020-11-27 16:22

I have a data.frame df and I want that every row in this df is duplicated lengthTime times and that a new column is added that counts

相关标签:
6条回答
  • 2020-11-27 16:56

    This works:

    REP <- rep(1:nrow(df), 3)
    df2 <- data.frame(df[REP, ], Time = rep(1:3, each = 9))
    rownames(df2) <- NULL
    df2
    
    0 讨论(0)
  • 2020-11-27 17:01

    Why not just something like df[rep(1:nrow(df),times = 3),] to extend the data frame, and then add the extra column just as you have above, with df$Time <- rep(1:lengthTime, each=nrRow)?

    0 讨论(0)
  • 2020-11-27 17:04

    Quick update

    There is now also the crossing() function in package tidyr which can be used instead of merge, is somewhat faster, and returns a tbl_df / tibble.

    data.frame(time=1:10) %>% merge(iris, by=NULL) 
    
    data.frame(time=1:10) %>% tidyr::crossing(iris) 
    
    0 讨论(0)
  • 2020-11-27 17:07

    A data.table solution:

    > 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
    

    Another one :

    > 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
    
    0 讨论(0)
  • 2020-11-27 17:08

    It's been a while since this question was posted, but I recently came across it looking for just the thing in the title, namely, an expand.grid that works for data frames. The posted answers address the OP's more specific question, so in case anyone is looking for a more general solution for data frames, here's a slightly more general approach:

    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)
    
    0 讨论(0)
  • 2020-11-27 17:11

    You can also just do a simple merge by NULL (which will cause merge to do simple combinatorial data replication):

    merge(data.frame(time=1:lengthTime), iris, by=NULL)
    
    0 讨论(0)
提交回复
热议问题