使用 data.table 中的多个键来获得条件搜索

2024-04-02

我有一个data.table首先,我想根据某些条件获得一个子集,例如,我有

library(data.table)
dt <- data.table(rn=1:10, B=rep(1:2, 5))
dt
#    rn B
# 1:  1 1
# 2:  2 2
# 3:  3 1
# 4:  4 2
# 5:  5 1
# 6:  6 2
# 7:  7 1
# 8:  8 2
# 9:  9 1
#10: 10 2`

我知道第一列名称,但我事先不知道第二列的名称,而是存储在字符向量中:nameAsVect <- "B"

假设我想获得以下内容:

dt[rn>5 & B==2, ]
#   rn B
#1:  6 2
#2:  8 2
#3: 10 2`

我想我可以这样做:

setkeyv(dt, c("rn", nameAsVect))
max.count <- max(dt[, nameAsVect, with=FALSE])
dt[J(5:max(rn), max.count), ]
#   rn B
#1:  5 2
#2:  6 2
#3:  7 2
#4:  8 2
#5:  9 2
#6: 10 2

但我不明白为什么列中的值是 5、7 和 9rn被包含在内。我可以通过以下方式获得我想要的东西:dt[rn>=5 & get(nameAsVect) == max.count]但我认为第一种方法如果有效的话,对于大表来说会更快。

有什么见解吗?

Thanks


OP 方法还有其他替代方法,不需要预先设置密钥

矢量扫描&get()

dt[rn >= 5 & get(nameAsVect) == max(get(nameAsVect))]
   rn B
1:  6 2
2:  8 2
3: 10 2

矢量扫描&eval(parse())

马特·道尔 (Matt Dowle) 在他的回答选择/分配给 data.table 变量,其名称存储在字符向量中 https://stackoverflow.com/a/12392269/3817004:

eval(parse(text = sprintf("dt[rn >= 5 & %s == max(%s)]", nameAsVect, nameAsVect)))
   rn B
1:  6 2
2:  8 2
3: 10 2

非等值连接

版本 v1.9.8(CRAN 2016 年 11 月 25 日发布),data.table已经获得了做事的能力非等值连接.

max.count <- dt[, max(get(nameAsVect))] 
dt[dt[.(5, max.count), on = c("rn>=V1", paste0(nameAsVect, "==V2")), which = TRUE]]
   rn B
1:  6 2
2:  8 2
3: 10 2

或者(我喜欢的方式)

mdt <- dt[, c(.(rn = 5), lapply(.SD, max)), .SDcols = nameAsVect] 
dt[dt[mdt, on = c("rn>=rn", nameAsVect), which = TRUE]]
   rn B
1:  6 2
2:  8 2
3: 10 2

基准

创建基准数据:

n_row <- 1e6L
set.seed(123L)
DT <- data.table(
  rn = sample(1:10, n_row, TRUE),
  B  = sample(1:2,  n_row, TRUE)
)

运行基准测试:

library(microbenchmark)
bm <- microbenchmark(
  vec_scan_hard_coded = {
    dt <- copy(DT)
    dt[rn >= 5L & B == 2L]
  },
  OP_keyed = {
    dt <- copy(DT)
    setkeyv(dt, c("rn", nameAsVect))
    max.count <- max(dt[, nameAsVect, with=FALSE])
    dt[J(5:max(rn), max.count), nomatch = 0L]
  },
  vec_scan_get = {
    dt <- copy(DT)
    dt[rn >= 5 & get(nameAsVect) == max(get(nameAsVect))]
  },
  vec_scan_eval_parse = {
    dt <- copy(DT)
    eval(parse(text = sprintf("dt[rn >= 5 & %s == max(%s)]", nameAsVect, nameAsVect)))
  },
  nej1 = {
    dt <- copy(DT)
    max.count <- dt[, max(get(nameAsVect))] 
    dt[dt[.(5, max.count), on = c("rn>=V1", paste0(nameAsVect, "==V2")), which = TRUE]]
  },
  nej1_keyed = {
    dt <- copy(DT)
    setkeyv(dt, c("rn", nameAsVect))
    max.count <- dt[, max(get(nameAsVect))] 
    dt[dt[.(5, max.count), on = c("rn>=V1", paste0(nameAsVect, "==V2")), which = TRUE]]
  },
  nej2 = {
    dt <- copy(DT)
    mdt <- dt[, c(.(rn = 5), lapply(.SD, max)), .SDcols = nameAsVect] 
    dt[dt[mdt, on = c("rn>=rn", nameAsVect), which = TRUE]]
  },
  nej2_keyed = {
    dt <- copy(DT)
    setkeyv(dt, c("rn", nameAsVect))
    mdt <- dt[, c(.(rn = 5), lapply(.SD, max)), .SDcols = nameAsVect] 
    dt[dt[mdt, on = c("rn>=rn", nameAsVect), which = TRUE]]
  },
  times = 100L
)
print(bm)

对于 1 M 行和大约 30 万行的结果集,矢量扫描方法是最快的:

Unit: milliseconds
                expr      min       lq     mean   median       uq      max neval cld
 vec_scan_hard_coded 19.03159 20.86890 42.70820 24.38040 27.57417 219.5682   100  a 
            OP_keyed 31.49025 34.50825 52.46168 37.74204 40.84953 194.7676   100  a 
        vec_scan_get 20.60384 25.75461 46.37579 27.29287 29.55892 185.5867   100  a 
 vec_scan_eval_parse 20.81188 23.92598 36.81940 26.69742 29.27687 183.5323   100  a 
                nej1 53.85361 59.32608 85.32623 62.12509 65.15083 227.1221   100   b
          nej1_keyed 52.89946 58.37457 77.38969 61.03312 64.32072 221.3292   100   b
                nej2 53.25590 59.69762 88.92513 61.98481 65.05738 285.2495   100   b
          nej2_keyed 53.25061 58.61453 81.22925 61.14885 63.56159 274.0207   100   b
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 data.table 中的多个键来获得条件搜索 的相关文章

随机推荐

  • 加密 web.config 失败错误

    我知道有人已经问过有关加密 web config 的问题 我还尝试加密我的测试配置文件 但我收到此错误 aspnet regiis pef connectionStrings C encryptedWeb config 正在加密配置部分 无
  • 从 Javascript 方法返回全局变量 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有一个方法 function ca
  • 在 PySpark 中读取 Lzo 文件

    我是 Spark 新手 我的文件夹中有一堆 LZO 索引文件 索引已完成 如上所示https github com twitter hadoop lzo https github com twitter hadoop lzo 文件如下 1
  • 如何检查所有列表项是否具有相同的值并返回它,或者如果没有则返回另一个值?

    如果列表中的所有项目都具有相同的值 那么我需要使用该值 否则我需要使用 otherValue 我想不出一个简单明了的方法来做到这一点 当列表为空时 它应该返回 其他 值 也可以看看编写对集合中的第一项具有特殊逻辑的循环的巧妙方法 https
  • JQGRID , 获取过滤后的所有行

    过滤 JQgrid 后 我无法获取所有行 分页 我试过 gt var myData grid jqGrid getGridParam data var myData grid jqGrid getRowData 但第一个选项给出了所有行 并
  • 崩溃时退出代码

    我想通过 shell 脚本知道应用程序是否崩溃 如果应用程序崩溃 退出代码是什么 应用程序的退出代码将位于 shell 变量中 如果您的应用程序崩溃 即操作系统认为它做了坏事 并导致它终止 向其发送信号 那么这会反映在退出状态中 这是我使用
  • 在 Excel VBA 中使用 COM 插件中的 CLR 类吗?

    我有一个 Excel VSTO COM 插件 我可以成功加载 Excel VBA 中的引用 我可以交换基本类型 如字符串 但我也可以在 VBA 中使用我的外接程序中的复杂类吗 假设我有 C 类 public class TestClass
  • 在 ggplot2 中使用 geom_point 有条件地使用抖动

    I have a graph with 12 variables divided into two groups I can t use facets but using colour and shape I have been able
  • 连接或级联多个预训练的 keras 模型

    我正在尝试构建一组串联或级联 实际上甚至不知道这是否是正确的定义 的模型 为了简单起见 我的基本模型如下所示 Input L1 1 L1 2 Dense
  • 通过 Javascript 解析 JSON 对象(对象列表)并在其中循环?

    好吧 我知道出了点问题 但我不明白是什么 我从我编写的 Web 服务中读取了 Service 的 ArrayList 采用 JSON 媒体类型 访问该地址会返回 json 字符串 现在我正在尝试制作一个网页来显示该值并查看每 3 秒请求一次
  • 状态栏和底部应用栏遮挡 WP 8.1

    我使用以下代码使状态栏显示在内容顶部 并设置背景不透明度 0 var applicationView Windows UI ViewManagement ApplicationView GetForCurrentView applicati
  • jQuery PickMeUp datepicker:禁用日期数组

    我正在使用一个名为的 jQuery 日期选择器插件PickMeUp https github com nazar pc PickMeUp 我的日期选择器可以工作 但无法弄清楚如何禁用其中的日期 我的计划是在日期选择器日历上禁用一系列日期 我
  • Exchange ItemID 与 Outlook 加载项的 GlobalAppointmentID 不同

    我遇到的问题是 使用 Outlook FormRegion 创建的 Outlook 约会的 GlobalAppointmentID 与使用 EWS 托管 API 时的 ItemID 不同 我正在创建一个 Outlook 插件 允许用户将客户
  • 1.7 中 javax.sql.CommonDataSource 添加了新方法

    尝试针对 java 1 7 编译我的应用程序 我发现 javax sql CommonDataSource 以及 j s DataSource 中 添加了一个新方法 getParentLogger 你可以比较一下通用数据源 1 7 http
  • 如何将 Guava ServiceManager 与 Guice 注入结合使用

    如上所述here https plus google com 118010414872916542489 posts 86dUfeQk5dH Guava ServiceManager 可以通过以下方式获取 ServiceManager ma
  • 检查 keyDown event.modifierFlags 会产生错误

    我继承 NSTextView 并覆盖 keyDown 我想检测命令键组合 例如 Command L 苹果的文档 https developer apple com library mac documentation Cocoa Concep
  • 酶测试嵌套组件的方法

    我正在尝试使用 Enzyme 来测试组件的方法 我知道执行此操作的典型方法是使用酶instance method 问题是 这只适用于root组件和我的组件需要包装在两个上下文提供程序中才能渲染 即react router和apollo客户端
  • 将 WPF 窗口附加到另一个进程的窗口

    我想编写一个 WPF 应用程序 该应用程序停靠到在另一个进程中运行的应用程序 这是我无法控制的第 3 方应用程序 理想情况下 我希望能够定义应用程序是停靠在左侧还是右侧 这是我想做的一个例子 我尝试实现以下 2 个示例 但没有成功 将窗口附
  • Meteor WebSocket 与 nginx 握手错误 400

    我设法在我的基础设施 Webfactions 上部署 Meteor 该应用程序似乎工作正常 但当我的应用程序启动时 我在浏览器控制台中收到以下错误 WebSocket connection to ws websocket failed Er
  • 使用 data.table 中的多个键来获得条件搜索

    我有一个data table首先 我想根据某些条件获得一个子集 例如 我有 library data table dt lt data table rn 1 10 B rep 1 2 5 dt rn B 1 1 1 2 2 2 3 3 1