1

ax列とy列を持つデータフレームを含む長さ30,000のリストがあります。データフレームはスパースであるため、xの各値が存在するわけではありません。すべてのx値は1から200の間です。

このリストを単一のデータフレームに変換したいのですが、可能なx値ごとに列があり、各行はリストエントリのすべてのy値を表す必要があります(ax値が存在しない場合、エントリは0である必要があります)。私にはうまくいく解決策がありますが(以下を参照)、それは非常に非常に遅く、そうするためのより速い(そしておそらくよりエレガントな方法)必要があると思います。

私の現在の解決策(遅い)は次のとおりです。

dat <- matrix(numeric(0), 30000, 200) 
for(i in seq(along=whaledatas)) {
    for(j in row.names(whaledatas[[i]]))
        dat[i, whaledatas[[i]][j,"x"]] <- whaledatas[[i]][j,"y"]
}

dfData <- data.frame(dat, files$label)
dfData[is.na(dfData)] <- 0 
4

3 に答える 3

4

妥当な時間がかかる答えは次のとおりです。

# function to create dummy data
my_sampler <- function(idx) {
    x <- sample(200, sample(50:100, 1))
    y <- sample(length(x))
    data.frame(x,y)
}

# create list of 30000 data.frames
in.d <- lapply(1:30000, function(x) my_sampler(x))

解決策:を使用するdata.table

require(data.table)
system.time(out.d <- do.call(rbind, lapply(in.d, function(x) {
    setattr(x, 'class', c("data.table", "data.frame")) # mnel's suggestion
    setkey(x, "x")
    x[J(1:200)]$y
})))

#   user  system elapsed 
# 47.111   0.343  51.283 

> dim(out.d)
# [1] 30000   200

# final step: replace NA with 0
out.d[is.na(out.d)] <- 0

編集: @regetzが示すように、最終的な行列を割り当ててから、xが発生する選択されたエントリをy値に置き換えるのは賢明です!@regetzのソリューションの小さなバリエーション:

m <- matrix(0.0, nrow=30000, ncol=200)
system.time(for( i in 1:nrow(m)) {
    m[i, in.d[[i]][["x"]]] <- in.d[[i]][["y"]]
})

#   user  system elapsed 
#  1.496   0.003   1.511 

これは、@ regetz(以下に表示)よりもさらに高速のようです。

> system.time(dat <- datify(in.d, xmax=200))
#   user  system elapsed 
#  2.966   0.015   2.993 
于 2013-03-11T21:37:58.980 に答える
1

私はdata.tableこのような解決策を使用します:

whaledatas <- lapply(1:30000,function(x)data.frame(x=1:200,y=1:200))
library(data.table)
dtt <- rbindlist(whaledatas)
于 2013-03-11T21:05:12.387 に答える
1

まず、データフレームのリストの小さな例を次に示します。

# create some sample data
whaledatas <- list(
    data.frame(x=1:3, y=11:13),
    data.frame(x=6:10, y=16:20)
)

forこれは元の質問のループと同じことだと思いますか?

# combine into single data frame
whaledatas.all <- do.call("rbind", whaledatas)

# change this to 200! kept small here for illustration...
XMAX <- 10

# create output matrix
dat <- matrix(0.0, length(whaledatas), XMAX)

# create index vector for dat rows
i <- rep(1:length(whaledatas), sapply(whaledatas, nrow))

# populate dat
dat[cbind(i, whaledatas.all[["x"]])] <- whaledatas.all[["y"]]

編集

入力のrbind数が増えると、はひどく遅くなります。このバージョン(便宜上関数にラップされている)はそれを回避し、はるかに高速に実行されます。

datify <- function(x, xmax=200) {
    dat <- matrix(0.0, length(x), xmax)
    for (i in seq_along(x)) {
        this.df <- x[[i]]
        coords <- cbind(rep(i, nrow(this.df)), this.df[["x"]])
        dat[coords] <- this.df[["y"]]
    }
    dat
}

ですべてゼロから始めたdatので、事後にそれを修正する必要はないことに注意してください...

> datify(whaledatas, xmax=10)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   11   12   13    0    0    0    0    0    0     0
[2,]    0    0    0    0    0   16   17   18   19    20

my_samplerArunの関数を使用して生成されたサンプルデータフレームの30kの長さのリストのタイミング:

set.seed(99)
in.d <- lapply(1:30000, function(x) my_sampler(x))
system.time(dat <- datify(in.d, xmax=200))
##   user  system elapsed 
##  1.317   0.011   1.328 
于 2013-03-11T21:15:07.483 に答える