ale*_*ing 4 r dplyr data.table
以下是我的data.frame的示例:
opts <- seq(-0.5, 0.5, 0.05)
df <- data.frame(combo1=sample(opts, 6),
combo2=sample(opts, 6),
combo3=sample(opts, 6),
gene=rep(c("g1", "g2", "g3"), each=2), stringsAsFactors=F)
df
combo1 combo2 combo3 gene
1 0.40 0.50 -0.10 g1
2 0.10 -0.20 -0.35 g1
3 -0.35 -0.35 0.40 g2
4 0.00 0.10 -0.30 g2
5 -0.45 -0.10 0.05 g3
6 -0.40 -0.40 -0.05 g3
Run Code Online (Sandbox Code Playgroud)
对于每个组合,我想按基因分组,然后选择最大绝对值.我可以使用dplyr完成此任务:
library(dplyr)
df_final <- data.frame(row.names=unique(df$gene))
for (combo in colnames(df)[1:3]) {
combo_preds <- df[, c(combo, "gene")]
colnames(combo_preds) <- c("pred", "gene")
combo_preds %>%
group_by(gene) %>%
arrange(desc(abs(pred))) %>%
slice(1) %>%
ungroup() ->
combo_preds
#add to df_final
class(combo_preds) <- "data.frame"
df_final[combo_preds$gene, combo] <- combo_preds$pred
}
#names rows based on gene
row.names(df_final) <- unique(df$gene)
df_final
combo1 combo2 combo3
g1 0.40 0.50 -0.35
g2 -0.35 -0.35 0.40
g3 -0.45 -0.40 0.05
Run Code Online (Sandbox Code Playgroud)
有没有办法可以使用data.table或其他更高效的实现来完成上述操作?实际上,我有~1300 dfs,每个有~14000个基因和~650个组合.目前的实施需要每分钟2.6分钟,因此需要2天.
你当然可以做到data.table.(我没有对你的版本做基准测试).
library(data.table)
dt <- data.table(df)
dt[, lapply(.SD, function (col) col[which.max(abs(col))]), by='gene']
Run Code Online (Sandbox Code Playgroud)
它基本上按基因对表进行分组,并在每个表的用途lapply上循环遍历每一列以查找具有最大绝对值的值.
但是,我认为你可能最好将表重新整理为长格式,但我认为这取决于你的具体数据(你必须试试看).
opts <- seq(-0.5, 0.5, 0.05)
n.combos <- 600
n.genes <- 10000
n.rows.per.gene <- 5
# columns are called X1 X2 instead of combo1 combo2 but no matter.
df.wide <- data.frame(replicate(n.combos, sample(opts, n.rows.per.gene, replace=T)),
gene=rep(paste0("g", 1:n.genes), each=n.rows.per.gene))
Run Code Online (Sandbox Code Playgroud)
这df.wide看起来像您的数据帧,每个组合一列,每个基因的每个重复一行.
这是最初的data.table答案:
# data.table option
library(data.table)
dt <- data.table(df.wide)
system.time({
out <- dt[, lapply(.SD, function (col) col[which.max(abs(col))]), by='gene']
})
# user system elapsed
# 10.757 0.364 12.612
Run Code Online (Sandbox Code Playgroud)
现在我们重塑为长格式,它只有一个'组合'列和一个'值'列:
# reshape to long
dt.long <- melt(dt, id.vars='gene', variable.name='combo')
# > head(dt.long)
# gene combo value
# 1: g1 X1 0.20
# 2: g1 X1 0.30
# 3: g1 X1 0.10
# 4: g1 X1 0.05
# 5: g1 X1 0.30
# 6: g2 X1 0.20
system.time({out.long <- dt.long[, value[which.max(value)], by='gene,combo']})
user system elapsed
8.000 0.472 9.525
Run Code Online (Sandbox Code Playgroud)
这为您提供了一个数据框,其中包含最大绝对值的基因,组合和值.如果你愿意的话,你可以重新塑造它.
所以它似乎没有那么快 - 我想你将不得不尝试在你的数据上看到.我想即使第二种方法更快,你仍然需要考虑将数据表转换为long所花费的时间(这看起来并不多).
比较例如dplyr(使用非常优雅,但速度较慢)
system.time({
out.dplyr <- df.wide %>% group_by(gene) %>%
summarise_each(funs(.[which.max(abs(.))]))
})
# user system elapsed
# 163.106 7.989 189.788
Run Code Online (Sandbox Code Playgroud)