替代expand.grid for data.frames

Chr*_*h_J 32 r

我有一个data.frame df,我希望这里的每一行df都是重复的lengthTime次数,并且添加了一个新的列,从1开始lengthTime计算每行df.

我知道,这听起来很复杂,但我基本上要为申请expand.griddf.这是一个丑陋的解决方法,我觉得有一个更简单的解决方案(甚至可能是一个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)
Run Code Online (Sandbox Code Playgroud)

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

yts*_*aig 57

自从这个问题发布以来已经有一段时间了,但是最近我发现它正在寻找标题中的东西,即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)
Run Code Online (Sandbox Code Playgroud)


jor*_*ran 17

为什么不只是像df[rep(1:nrow(df),times = 3),]扩展数据框,然后像上面一样添加额外的列df$Time <- rep(1:lengthTime, each=nrRow)


Hol*_*ndl 13

你也可以简单地merge使用NULL合并列(这将导致merge简单的组合数据复制):

merge(data.frame(time=1:lengthTime), iris, by=NULL)
Run Code Online (Sandbox Code Playgroud)


小智 9

快速更新

现在还有包tidyr中的crossing()函数,它可以用来代替merge,有点快,并返回一个tbl_df/tibble.

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

data.frame(time=1:10) %>% tidyr::crossing(iris) 
Run Code Online (Sandbox Code Playgroud)