使用返回向量的函数中的行创建data.frame

时间:2015-04-30 16:59:06

标签: r dataframe

我有许多单独的csv文件中的数据,我想创建一个data.frame,每个文件都有一行。下面的函数提供了用于每一行的数据。我不想更改此代码,例如包括输出向量的farmid部分。

vectorfromfile <- function(farmid) {
    # Reads data from a file named farm{id}.csv, eg 
    # farm001.csv, and returns one named vector
    # of length two with class numeric and names 'apples' 
    # and 'oranges' An example could be c(apples=4, oranges=6)

    # The line below is a dummy for test purposes
    c(apples=farmid+1000, oranges=farmid+2000)
}
然后我有一个载体,农场,例如农场&lt; - c(1,3,5)。我需要创建一个包含三列的数据框:id,apples和oranges,以及每个farmids的一行。它应该看起来像下面定义的data.frame。

> data.frame(id=c(1,3,5), apples=c(4,2,3), oranges=c(6,5,2) )
  id apples oranges
1  1      4       6
2  3      2       5
3  5      3       2

我找到了几种方法,所有这些方法都非常难看,占用了很多行。但我想以最优雅的方式使用split-apply-combine方法。所以我希望我可以简单地应用(迭代)一个向量,并得到一个data.frame作为结果。像

这样的东西
apply(farmids, ???? ) # farmids is  a vector

这可能吗?如果没有,那么可能迭代一个具有相同值的列表?即使这是不可能的,那么最优雅的方式是什么呢。

我在下面的丑陋尝试

vect2df_v1 <- function(farmids=c(1,3,5)) {
    df <- data.frame(id=farmids, apples=rep(NA, length(farmids)), oranges=rep(NA, length(farmids)))
    for (i in 1:length(farmids)) {
       df[i, c('apples', 'oranges')] <- vectorfromfile(df[i, 'id'])
    }
    df
}

vect2df_v2 <- function(farmids=c(1,3,5)) {
    # Obviously it could be written into one (even uglier) line
    farmrow <- function(farmid) { c(farmid, vectorfromfile(farmid)) }
    lst <- lapply(farmids, farmrow)
    mtrx <- matrix(unlist(lst), ncol=3, byrow=T, dimnames=list(NULL,c('id', 'apples','oranges')))
    data.frame(mtrx)
}

1 个答案:

答案 0 :(得分:1)

do.call(rbind, ...)很简单。

您可以这样写vect2df

vect2df <- function(vec) {
  data.frame(id = vec, do.call(rbind, lapply(vec, vectorfromfile)))
} 

演示:

vect2df(c(1, 3, 5))
#   id apples oranges
# 1  1   1001    2001
# 2  3   1003    2003
# 3  5   1005    2005

当然,这可以通过within直接完成(如果vectorfromfile不是关键功能,但可以简单定义。

示例:

within(data.frame(id = c(1, 3, 5)), {
  oranges <- id + 2000
  apples <- id + 1000
})
#   id apples oranges
# 1  1   1001    2001
# 2  3   1003    2003
# 3  5   1005    2005