我猜有趣的數據是一個真正的矩陣
m = as.matrix(sample[,-1])
底層數據是一個具有相對較少的唯一值的向量;我們唯一值映射到它們的整數表示,使用地圖,可以最小化是必要
s = as.character(m)
map = lapply(strsplit(setNames(unique(s), unique(s)), "/"), as.integer)
這裏的每一行需要複製的次數任意循環迭代次數
row.len = apply(matrix(sapply(map, max)[s], ncol=ncol(m)), 1, max) + 1
和偏移到每個行
offset = head(c(1, cumsum(rep(row.len, ncol(m))) + 1), -1)
計算每個映射元素的值的s
,並且在012的值的索引
v = unlist(unname(map)[match(s, names(map))])
idx = rep(offset, sapply(map, length)[s]) + v
最後,分配NA的結果矩陣,並更新非NA值
ans = matrix(NA_integer_, sum(row.len), ncol(m))
ans[idx] = v
作爲功能:
flatten <- function(sample) {
m = as.matrix(sample[,-1])
s = as.character(m)
map = lapply(strsplit(setNames(unique(s), unique(s)), "/"), as.integer)
row.len = apply(matrix(sapply(map, max)[s], ncol=ncol(m)), 1, max) + 1
offset = head(c(1, cumsum(rep(row.len, ncol(m))) + 1), -1)
v = unlist(unname(map)[match(s, names(map))])
idx = rep(offset, sapply(map, length)[s]) + v
ans = matrix(NA_integer_, sum(row.len), ncol(m),
dimnames=list(NULL, colnames(sample)[-1]))
ans[idx] = v
cbind(POS=rep(sample[,1], row.len), as.data.frame(ans))
}
這樣做的最慢的部分將是apply
函數計算row.len
。一些時間(我猜這個尺寸對於這個問題是不正確的......)
xx = do.call(rbind, replicate(10000, sample, simplify=FALSE))
dim(xx)
## [1] 30000 5
system.time(flatten(xx))
## user system elapsed
## 0.192 0.000 0.194
對比上面的data.table解決方案大約5s。
您是否主要需要*工作*或主要工作*快速*?你到目前爲止嘗試過什麼嗎? –
我假設0/1/2總是按順序。 –
另外,爲什麼你需要這個 - 例如,轉換成位域不是一樣有效? (也要快得多) –