【问题标题】:Dynamically allocate a data.frame with grace优雅地动态分配一个data.frame
【发布时间】:2014-08-18 08:09:21
【问题描述】:

我有一个数据框应该在运行时增长(添加行)。明智的做法是预先分配数据帧 (cmp.The R Inferno)。预分配例程应该接受所有类型的数据框组合(即列数和列类)。

示例

arbitraryDf<-function(){
    return(data.frame(C="char",L=TRUE,N=4.5,stringsAsFactors=FALSE))
}

返回一个任意数据框以用作模板。我需要N &lt;- 10 行,所以我可能会这样做:

data<-as.data.frame(lapply(arbitraryDf(),function(x){eval(parse(text=paste(class(x),"(",N,")")))}),stringsAsFactors=FALSE)

返回所需的数据帧。

>data
   C     L N
1    FALSE 0
2    FALSE 0
3    FALSE 0
4    FALSE 0
5    FALSE 0
6    FALSE 0
7    FALSE 0
8    FALSE 0
9    FALSE 0
10   FALSE 0
>sapply(data,class)
          C           L           N 
"character"   "logical"   "numeric" 

不用说,eval() 的使用是丑陋的。有没有更直接的解决方案?

如前所述,例程需要接受任何数据帧组合,否则@mnel's answer 就足够了。

更新

本质上,我想达到和

一样的效果
data <- data.frame(x= numeric(N), y= integer(N), z = character(N)) 

但以通用方式,适用于任何 df 布局。 df 布局的信息应该从给定的 df 中绘制(这里是任意的 Df())

【问题讨论】:

  • 您在寻找类似do.call(rbind, replicate(N, arbitraryDf(), FALSE)) 的东西吗?你到底想达到什么目的?
  • @Ananda 如前所述,目标是分配一个数据帧。列号和类在运行前是未知的。您的解决方案很好,但也复制了 data.frame 的内容
  • 我将使用vector 函数进行分配,但是您没有提供足够的详细信息来正确建议,您的用例没有得到很好的解释。我看不出rbinding 一个完整的行与[&lt;- 子集和替换有任何区别。如果你不得不预先分配我会看例如N &lt;- 10;df &lt;- data.frame( n = vector("numeric",N) , c = vector("character",N) )

标签: r dataframe


【解决方案1】:

我不确定这是否是您要找的。函数gendf 有两个参数——模板数据框和行数。它根据给定行数的模板返回空数据框。

arbitraryDf <- data.frame(C = "char", L = T, N = 4.5, stringsAsFactors = F)
arbitraryDf

gendf <- function(df, N) {
  # Create list of modes
  modes <- lapply(df, storage.mode)
  # Return data.frame
  return(data.frame(lapply(modes, vector, N)))
}

x <- gendf(arbitraryDf, 10)
class(x)

【讨论】:

  • 倒霉。看起来阿难达比你快了 8 秒!无论如何 +1。
【解决方案2】:

为了概括西蒙的评论,也许这样的东西对你有用:

myFun <- function(sourceDF, length) {
  Classes <- sapply(sourceDF, class)
  data.frame(lapply(Classes, vector, length = length))
}

在这里,我们首先提取源data.frame 的每一列的类,并将其用作新data.frame 的模板,其长度由length 参数确定。

例子:

myFun(arbitraryDf(), 5)
#   C     L N
# 1   FALSE 0
# 2   FALSE 0
# 3   FALSE 0
# 4   FALSE 0
# 5   FALSE 0

【讨论】:

  • +1,但是 是否真的从预分配然后(我假设)子集和替换行而不是仅仅对它们进行绑定来提高性能?我对此表示怀疑(但我还没有测试过)。
  • @Ananda。很不错。可以肯定的是,返回值应为:data.frame(...,stringsAsFactors=FALSE),因为对于不添加新级别的因素,您将无法插入任何值
  • 是的,@Simon,绝对和彻底。参考R-Inferno p12 for timings
  • @Jan,我不认为 Simon 在质疑预分配的价值,但这是否是解决您问题的最佳解决方案(我仍然不完全理解)。
  • @Ananda,也许是我的错。不用说,上面只是一个游戏示例——可能不是一个好例子。做了rbinding,现在通过分配和子集来改进。它快了很多。特别是在大数据集上。谢谢。
猜你喜欢
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 2012-04-16
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
相关资源
最近更新 更多