雖然看起來很奇怪,但您需要了解的一點是,數據幀的速度非常慢。每一個修改數據幀的操作都是昂貴的,並且unsplit
正在做的是通過重新插入修改每個分割的數據幀。每次修改內部邏輯時都需要複製整個數據幀。這就是所謂的爲unsplit
部分:
`split<-.data.frame`
function (x, f, drop = FALSE, ..., value)
{
ix <- split(seq_len(nrow(x)), f, drop = drop, ...)
n <- length(value)
j <- 0
for (i in ix) {
j <- j%%n + 1
x[i, ] <- value[[j]]
}
x
}
<bytecode: 0x7ffd5e282c68>
<environment: namespace:base>
x
這裏是初始化爲你的結果的大小data.frame,你可以看到,基本上我們插入它每分裂。由於您的數據幀非常龐大,因此每個插入的代價都非常高。爲了強調爲什麼這是可怕的,考慮下面的例子,我們用數據框中的一列中的每個值進行基準測試,而對等效矩陣做同樣的事情。儘管我們做的是完全一樣的東西,但數據幀版本慢了30倍!這是爲了一個微小的數據框。當data.frame很大時,你可以很快看到這到底是怎麼回事。
df <- data.frame(a=seq(1:100), b=runif(100), c=sample(1:10, 100, rep=T))
mx <- as.matrix(df)
microbenchmark(for(i in 1:nrow(df)) df[i, 2] <- 1)
# Unit: milliseconds
# expr min lq median uq max neval
# for (i in 1:nrow(df)) df[i, 2] <- 1 4.018833 4.273562 4.584293 4.726672 23.46349 100
microbenchmark(for(i in 1:nrow(mx)) mx[i, 2] <- 1)
# Unit: microseconds
# expr min lq median uq max neval
# for (i in 1:nrow(mx)) mx[i, 2] <- 1 148.304 153.9795 158.5975 163.7065 277.861 100
順便說一句,這就是爲什麼在上述類型的操作的建議是先計算向量,並在結束更換向量到數據幀列,以便只修改數據幀一次。
回覆:使用data.table
或dplyr
,我挑戰你張貼的問題分析的類型,你與split
/unsplit
做,我懷疑你會被這些軟件包多麼強大可以解決你的問題感到驚訝。
你是否檢查過你的RAM分配?如果你咀嚼了所有這些,就會發生很多交換,導致更長的執行時間。如果你在'k * 1e5'塊上運行一個循環,看看會發生什麼。 –
你真的需要擁有和以前一樣的數據嗎?如果不考慮只使用'do.call(rbind,split(data,data $ mid))',這在我的測試中看起來要快一點。 – nograpes
另外,你可以添加一些代碼來生成像你這樣的數據,例如:'n <-1e7; d <-data.frame(d = factor(sample(1:10,n,replace = TRUE)),v = RNORM(N),V2 = RNORM(N),V3 = RNORM(N))'。我很難生成足夠大的數據,而這些數據在30秒內不會完成。 – nograpes