通过查找按组快速 data.table 分配多列

2024-04-15

我一直在寻找规范的方法来完成我正在尝试的事情,但我似乎不太幸运地获得快速而优雅的工作。简而言之,我有一个包含多个值列的大表,并且希望将每个值乘以查找表中的相应因子。我不知道如何动态传递我想要乘以查找值的列,或者如何在基本表达式之外引用查找值。

这是我的示例,我将其设置为 300 万行和 10 个值列,这不会花费太长时间,并且在某种程度上代表了数据大小(这将作为更大循环的一部分来实现,因此强调关于性能)。还有一个包含 6 个级别的查找表以及一些用于 value_1:value_10 列的分类乘数。

library(data.table)

setsize <- 3000000
value_num <- 10
factors <- c("factor_a", "factor_b", "factor_c", "factor_d", "factor_e", "factor_f")
random <- data.table(replicate(10, sample(factors, size = setsize,  replace = T))
                     , replicate(10, rnorm(setsize, mean = 700, sd = 50)))
lookup <- data.table("V1" = factors, replicate(10, seq(.90, 1.5, length.out = length(factors))))
wps <- paste("value", c(1:10), sep = "_")
names(random)[11:20] <- wps
names(lookup)[2:11] <- wps
setkeyv(random, "V1")
setkeyv(lookup, "V1")

解决方案 1:速度相当快,但我不知道如何通用地引用 i 列,例如i.value_1所以我可以将它们传递到一个循环中,或者更好的是一次性应用它们。

f <- function() {
  random[lookup, value_1 := value_1 * i.value_1, by = .EACHI]
  random[lookup, value_2 := value_2 * i.value_2, by = .EACHI]
  random[lookup, value_3 := value_3 * i.value_3, by = .EACHI]
  random[lookup, value_4 := value_4 * i.value_4, by = .EACHI]
  random[lookup, value_5 := value_5 * i.value_5, by = .EACHI]
  random[lookup, value_6 := value_6 * i.value_6, by = .EACHI]
  random[lookup, value_7 := value_7 * i.value_7, by = .EACHI]
  random[lookup, value_8 := value_8 * i.value_8, by = .EACHI]
  random[lookup, value_9 := value_9 * i.value_9, by = .EACHI]
  random[lookup, value_10 := value_10 * i.value_10, by = .EACHI]
}

system.time(f())

   user  system elapsed 
  0.184   0.000   0.181 

解决方案 2:在我无法使解决方案 1 通用后,我尝试了set()基于的方法。然而,尽管允许我在字符向量中指定目标值列wps,实际上比上面慢很多。我知道我用错了它,但不确定如何改进它以消除所有 [.data.table 开销。

idx_groups <- random[,.(rowstart = min(.I), rowend = max(.I)), by = key(random)][lookup]
system.time(
for (i in 1:nrow(idx_groups)){
  rows <- idx_groups[["rowstart"]][i]:idx_groups[["rowend"]][i]
  for (j in wps) {
    set(random, i=rows, j=j, value= random[rows][[j]] * idx_groups[[j]][i])
  }  
})

   user  system elapsed 
  3.940   0.024   3.967 

任何有关如何更好地构建这些操作的建议将不胜感激。

编辑:我对自己感到非常沮丧,因为在发布这个问题之前未能尝试这个明显的解决方案:

system.time(
for (col in wps){
  random[lookup, (col) := list(get(col) * get(paste0("i.", col))), by = .EACHI, with = F]
})

   user  system elapsed 
  1.600   0.048   1.652 

这似乎以相对速度做我想做的事。然而它仍然比上面第一个解决方案慢 10 倍(我确信由于重复get())所以我仍然愿意接受建议。

编辑2:替换get() with eval(parse(text=col))似乎已经成功了。

system.time(
for (col in wps){
  random[lookup, (col) := list(eval(parse(text=col)) * eval(parse(text=paste0("i.", col)))), by = .EACHI, with = F]
})
   user  system elapsed 
  0.184   0.000   0.185 

编辑3:已经提供了几个很好的工作答案。 Rafael 的解决方案在一般情况下可能是最好的,尽管我会注意到,我可以从 Jangorecki 推荐的调用构造中多挤出几毫秒,以换取看起来相当吓人的辅助函数。我已将其标记为已回答,谢谢大家的帮助。


您还可以使用lapply:

cols <- noquote(paste0("value_",1:10))

random[lookup, (cols) := lapply (cols, function(x)  get(x) * get(paste0("i.", x))), by = .EACHI ]

如果您的数据集太大并且您想查看操作的进度条,您可以使用pblapply:

library(pbapply)

random[lookup, (cols) := pblapply(cols, function(x)  get(x) * get(paste0("i.", x))), by = .EACHI ]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过查找按组快速 data.table 分配多列 的相关文章

随机推荐

  • 摇动:发出是否需要重建任何东西的信号

    我使用 shake 构建了一堆静态网页 然后我必须使用 sftp 将其上传到远程主机 目前 cronjob 运行 git pull get possibly updated sources my shake system lftp uplo
  • org.w3c.dom.Document 转换为字符串,无需 javax.xml.transform

    我花了一段时间在 Google 上寻找一种将 org w3c dom Document 转换为整个 DOM 树的字符串表示形式的方法 这样我就可以将对象保存到文件系统中 然而 我发现的所有解决方案都使用 javax xml transfor
  • KubernetesExternalName服务在DNS中不可见

    我正在尝试将单个数据库实例公开为两个 Kubernetes 命名空间中的服务 Kubernetes 版本 1 11 3 在 Ubuntu 16 04 1 上运行 数据库服务是可见的并且在默认命名空间中工作 我在非默认命名空间中创建了一个Ex
  • 打造 ecto 独一无二的领域

    如何制作一个字段unique在体外 我以为它和Ruby中的活动记录一样 但似乎不是 你想使用唯一约束 3 http hexdocs pm ecto Ecto Changeset html unique constraint 3 这与 Act
  • 如果 MySQL 中的行不存在,则添加到该行

    当向表中添加一行时 但首先检查它是否存在哪种处理方法最有效 是否是查询是否存在的情况 如果不存在则插入 或者重复使用 或者简单地替换 如果该行不存在 这会起作用 吗 Thanks 我认为这是 MySQL 中最快的方法 REPLACE int
  • 不可变类型:公共最终字段与 getter

    我需要一个小的容器类来存储一些应该不可变的字符串 由于 String 本身是不可变类型 所以我想到了类似的东西 public final class Immu public final String foo public final Str
  • 从 airodump-ng 读取实时输出

    当我执行命令 airodump ng mon0 gt gt output txt 时 output txt 为空 我需要能够运行 airodump ng mon0 并在大约 5 秒后停止该命令 然后才能访问其输出 有什么想法我应该从哪里开始
  • 如何以良好的格式结果格式化 python 列表

    我有很多列表 如下所示 通过打印data并将其与字符串连接起来check str如下最后一条语句所示 需要帮助以在字符串连接后更好地格式化列表值 如预期所示 print data printing lists in this variabl
  • 图像上的文本没有绝对位置

    我正在尝试在页面中间的图像上放置一些文本 我看到一个这样的例子 img src image png p p p p
  • 在 docker 容器上保存配置

    我创建了 2 个 docker 容器 并尝试在 ubuntu debian 上安装一些应用程序和一些软件包 如 mc ping traceroute 但每当我退出容器时 我都会丢失其中的所有内容 是否有任何 docker 命令可以保存我的配
  • 从具有特定模式的 txt 文件创建 Pandas DataFrame

    我需要基于以下结构的文本文件创建一个 Pandas DataFrame Alabama edit Auburn Auburn University 1 Florence University of North Alabama Jackson
  • .NET Framework 全局程序集缓存在哪里?

    我安装了 VS2010 和 NET 4 0 然后编译了一个程序集并使用可用的 exe 运行 gacutil ProgramFiles Microsoft SDKs Windows v7 0A Bin NETFX 4 0 Tools 可执行文
  • 如何在 R 中重新格式化表格?

    我加载了一个这样的表 V1 V2 V3 pat1 1 2 pat1 3 1 pat1 4 2 pat2 3 3 pat3 1 4 pat3 2 3 我需要将其格式化为如下所示 其中 V1 表示行 V2 表示列 V3 中的值 1 2 3 4
  • Android 中未接来电的广播接收器

    有谁知道未接来电的意图是什么 实际上 我想在我的应用程序中发送有关未接来电和来电的短信 您需要使用 ContentObserver public class MissedCallsContentObserver extends Conten
  • fork 后调试子进程(配置了 follow-fork-mode 子进程)

    我正在开发一个应用程序 父级分叉子级来处理某些任务 我遇到一个问题 我已将 gdb 配置为 follow fork mode 子级 但在 fork 后 到达断点后 它发送 SIGTRAP 但子级以某种方式终止并向父级发送 SIGCHLD 我
  • 数据表行切换选项

    我的问题 我正在开发一个与 DataTableJS 相关的项目 我需要一个行分组功能 它与分组行分开 只是我想在下面的切换中显示相关的表行内容城市名 我到底在寻找什么 我的演示代码 document ready function var t
  • Swagger 无法生成 HTTP“PATCH”的文档

    我已遵循以下内容博客条目 http kingsfleet blogspot co uk 2014 02 transparent patch support in jax rs 20 html http Transparent 20PATCH
  • 在 htaccess 文件中使用公用文件夹时的多种语言

    我有这个 htacces文件我很喜欢它 但是如何向它添加多语言 所以它明白localhost en 不是文件或文件夹 现在它使用公共文件夹作为 根 所以localhost public 如果我想这样做 那太好了 我仍然使用公共文件夹作为根目
  • JetBrains(IntelliJ、PhpStorm、WebStorm ...)带有 SSH 密钥的私有 git 存储库

    我的新 Web 服务器需要使用 RSA 2048 密钥进行身份验证 因此我生成了一个密钥 我将ir rsa and id rsa pub我的主文件夹中的文件 ssh Windows 10 但是当我使用 cvs 注释 用于拉或推 时 我收到错
  • 通过查找按组快速 data.table 分配多列

    我一直在寻找规范的方法来完成我正在尝试的事情 但我似乎不太幸运地获得快速而优雅的工作 简而言之 我有一个包含多个值列的大表 并且希望将每个值乘以查找表中的相应因子 我不知道如何动态传递我想要乘以查找值的列 或者如何在基本表达式之外引用查找值