有效检查 data.table 中其他行的值

2024-01-05

Note:这是我最初发布到 data.table 帮助组的一个问题。马特·道尔(Matt Dowle)要求提供更详细的示例,我发布了这个示例,但我在电子邮件格式方面遇到了麻烦。我已经知道如何格式化 SO,所以我想我应该将其发布在这里。

我基本上想做的是根据该行中的值从 data.table 中提取行前一行或后一行中的值。现在,我正在为未来和过去的行创建新列,然后在这些列上键入 data.table,但这是资源密集型且繁重的。

下面的例子说明了我现在使用的方法。该示例使用文档中的单词(我对两者都使用数字索引)。我想对特定单词进行子集化,但前提是它前面或后面有另一个单词或一组单词:

我首先创建一个虚拟数据集,其中包含 10 个包含 100 万个单词的文档。该集中有三个独特的单词。

library(data.table)
set.seed(1000)
DT<-data.table(wordindex=sample(1:3,1000000,replace=T),docindex=sample(1:10,1000000,replace=T))
setkey(DT,docindex)
DT[,position:=seq.int(1:.N),by=docindex]


          wordindex docindex position
      1:         1        1        1
      2:         1        1        2
      3:         3        1        3
      4:         3        1        4
      5:         1        1        5
    ---                            
 999996:         2       10    99811
 999997:         2       10    99812
 999998:         3       10    99813
 999999:         1       10    99814
1000000:         3       10    99815

请注意,简单地计算所有文档中第一个唯一单词的出现次数既简单又美观。

setkey(DT,wordindex)
count<-DT[J(1),list(count.1=.N),by=docindex]
count

    docindex count.1
 1:        1   33533
 2:        2   33067
 3:        3   33538
 4:        4   33053
 5:        5   33231
 6:        6   33002
 7:        7   33369
 8:        8   33353
 9:        9   33485
10:       10   33225

当考虑到前面的位置时,情况会变得更加混乱。这是一个计算所有文档中第一个唯一单词出现次数的查询unless接下来是第二个独特的词。首先,我创建一个新列,其中包含前面一个位置的单词,然后键入这两个单词。

setkey(DT,docindex,position)
DT[,lead_wordindex:=DT[list(docindex,position+1)][,wordindex]]

         wordindex docindex position lead_wordindex
      1:         1        1        1              1
      2:         1        1        2              3
      3:         3        1        3              3
      4:         3        1        4              1
      5:         1        1        5              2
     ---                                           
 999996:         2       10    99811              2
 999997:         2       10    99812              3
 999998:         3       10    99813              1
 999999:         1       10    99814              3
1000000:         3       10    99815             NA

setkey(DT,wordindex,lead_wordindex)
countr2<-DT[J(c(1,1),c(1,3)),list(count.1=.N),by=docindex]
countr2

    docindex count.1
 1:        1   22301
 2:        2   21835
 3:        3   22490
 4:        4   21830
 5:        5   22218
 6:        6   21914
 7:        7   22370
 8:        8   22265
 9:        9   22211
10:       10   22190

我有一个非常大的数据集,上述查询的内存分配失败。作为替代方案,我们可以通过过滤原始数据集然后将其连接回所需位置,仅为相关数据子集创建此新列:

setkey(DT,wordindex)
filter<-DT[J(1),list(wordindex,docindex,position)]
filter[,lead_position:=position+1]

        wordindex wordindex docindex position lead_position
     1:         1         1        2    99717         99718
     2:         1         1        3    99807         99808
     3:         1         1        4   100243        100244
     4:         1         1        1        1             2
     5:         1         1        1       42            43
    ---                                                    
332852:         1         1       10    99785         99786
332853:         1         1       10    99787         99788
332854:         1         1       10    99798         99799
332855:         1         1       10    99804         99805
332856:         1         1       10    99814         99815

setkey(DT,docindex,position)
filter[,lead_wordindex:=DT[J(filter[,list(docindex,lead_position)])][,wordindex]]

        wordindex wordindex docindex position lead_position lead_wordindex
     1:         1         1        2    99717         99718             NA
     2:         1         1        3    99807         99808             NA
     3:         1         1        4   100243        100244             NA
     4:         1         1        1        1             2              1
     5:         1         1        1       42            43              1
    ---                                                                   
332852:         1         1       10    99785         99786              3
332853:         1         1       10    99787         99788              3
332854:         1         1       10    99798         99799              3
332855:         1         1       10    99804         99805              3
332856:         1         1       10    99814         99815              3

setkey(filter,wordindex,lead_wordindex)
countr2.1<-filter[J(c(1,1),c(1,3)),list(count.1=.N),by=docindex]
countr2.1

    docindex count.1
 1:        1   22301
 2:        2   21835
 3:        3   22490
 4:        4   21830
 5:        5   22218
 6:        6   21914
 7:        7   22370
 8:        8   22265
 9:        9   22211
10:       10   22190

我觉得很丑。此外,我可能想要查看多个单词,因此需要创建另一栏。简单但昂贵的方法是:

setkey(DT,docindex,position)
DT[,lead_lead_wordindex:=DT[list(docindex,position+2)][,wordindex]]

         wordindex docindex position lead_wordindex lead_lead_wordindex
      1:         1        1        1              1                   3
      2:         1        1        2              3                   3
      3:         3        1        3              3                   1
      4:         3        1        4              1                   2
      5:         1        1        5              2                   3
     ---                                                               
 999996:         2       10    99811              2                   3
 999997:         2       10    99812              3                   1
 999998:         3       10    99813              1                   3
 999999:         1       10    99814              3                  NA
1000000:         3       10    99815             NA                  NA

setkey(DT,wordindex,lead_wordindex,lead_lead_wordindex)
countr23<-DT[J(1,2,3),list(count.1=.N),by=docindex]
countr23

    docindex count.1
 1:        1    3684
 2:        2    3746
 3:        3    3717
 4:        4    3727
 5:        5    3700
 6:        6    3779
 7:        7    3702
 8:        8    3756
 9:        9    3702
10:       10    3744

然而,由于尺寸的原因,我目前不得不使用丑陋的过滤和连接方式。

那么问题来了,有没有更简单、更美观的方式呢?

UPDATE:

感谢 Arun 和 eddi 提供了解决问题的干净简单的代码。在我的约 200M 行数据上,这个解决方案可以在大约 10 秒内处理简单的单词组合,这非常好!

然而,我确实有一个额外的问题,这使得矢量扫描方法不太理想。尽管在示例中我只查找一个单词组合,但实际上我可能在每个位置都有一个单词向量要查找。当我出于此目的将“==”语句更改为“%in%”(100 个或更多单词的向量)时,查询需要更长的时间才能运行。因此,如果存在的话,我仍然对二分搜索解决方案感兴趣。然而,如果阿伦不知道,那也可能不知道,我很乐意接受他的回答。


这是我脑海中突然出现的另一个想法。它只需要再创建一列并使用二分查找对于子集。

On the DT您已经根据数据生成了,首先我们将添加额外的列:

# the extra column:
DT[, I := .I]

我们需要这个,因为我们将setkey on docindex and wordindex。这是我们可以在不创建额外列的情况下进行子集化的唯一方法(至少是我能想到的)。因此,我们需要一种方法来提取“原始”位置,以检查您的情况(因此I).

添加额外的列后,让我们在上面提到的两列上设置键:

setkey(DT, docindex, wordindex)

伟大的!这里的想法是提取位置您想要的单词匹配的位置 - 这里的值是1L。然后,提取您可能想要(或可能不想)出现在该单词之后的正确位置的所有其他单词。然后,我们只需保留(或删除)那些满足条件的索引即可。

这是一个可以处理这个问题的函数。它绝不是完整的,但应该可以给您一个想法。

foo <- function(DT, doc_key, word_key, rest_key=NULL, match=FALSE) {
    ## note that I'm using 1.9.3, where this results in a vector
    ## if you're using 1.9.2, you'll have to change the joins accordingly
    idx1 = DT[J(doc_key, word_key), I]
    for (i in seq_along(rest_key)) {
        this_key = rest_key[i]
        idx2 = DT[J(doc_key, this_key), I]
        if (match) idx1 = idx1[which((idx1+i) %in% idx2)]
        else idx1 = idx1[which(!(idx1+i) %in% idx2)]
    }
    DT[idx1, .N, by=c(key(DT)[1L])]
}

Here, DT is the data.table到哪个I已添加栏目,and then setkey如前所述,已在两列上调用。

doc_key基本上包含了所有的唯一值docindex- 这里 1 点 10 分。word_key这里基本上是1L。rest_key是您要检查的值没有出现在i的位置之后的第 个位置word_key.

首先我们提取I对于所有比赛1L in idx1(直截了当)。接下来我们循环遍历的每个值rest_key并将该位置添加到idx1 = idx1+i并检查该值是否出现在idx2。如果是这样,根据您是否喜欢提取matching or 不匹配条目,我们将保留(或删除它们)。

在这个循环结束时,idx1应该只有所需的条目。希望这可以帮助。下面显示的是其他答案中已经讨论过的案例的演示。


让我们考虑您的第一个场景。中每个组的所有条目计数docindex第 i 个位置是1L and i+1th is not2L。这基本上是:

system.time(ans1 <- foo(DT, 1:10, 1L, 2L, FALSE))

#  user  system elapsed 
# 0.066   0.019   0.085 

# old method took 0.12 seconds

#     docindex     N
#  1:        1 22301
#  2:        2 21836
#  3:        3 22491
#  4:        4 21831
#  5:        5 22218
#  6:        6 21914
#  7:        7 22370
#  8:        8 22265
#  9:        9 22211
# 10:       10 22190

那么第二种情况呢?在这里,我们想要i+1th and i+2th 位置为 2L 和 3L,而不是不等于先前案例中的场景。所以,我们设置match=TRUE here.

system.time(ans2 <- foo(DT, 1:10, 1L, 2:3,TRUE))
#  user  system elapsed 
# 0.080   0.011   0.090 

# old method took 0.22 seconds

#     docindex    N
#  1:        1 3684
#  2:        2 3746
#  3:        3 3717
#  4:        4 3727
#  5:        5 3700
#  6:        6 3779
#  7:        7 3702
#  8:        8 3756
#  9:        9 3702
# 10:       10 3744

扩展这个功能很容易。例如:如果你想要i+1th 等于2L but i+2th 不等于 to 3L然后,你可以改变match成为一个向量=length(rest_key)指定相应的逻辑值。

我希望这对于您的实际情况来说很快 - 至少比其他版本更快。

HTH

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有效检查 data.table 中其他行的值 的相关文章

  • 使用faceting()时如何连接geom_point()和geom_line?

    我有一个问题 但我在互联网上没有找到任何相关信息 我很高兴得到一些提示 我有一个数据集 其中 x 轴是离散的 但我想将这些点相互连接 我可以做到 我的问题是当我添加分面选项时 我无法再将这些点相互链接起来 我找到了一个替代方案 但看起来不太
  • 如何通过组度量的平均值在 df 内排列 dplyr:: 组?

    借鉴吴卡拉的设计https stackoverflow com a 26555424 9350837 https stackoverflow com a 26555424 9350837答案 我希望根据各个组汇总测量的平均值对分组 df 进
  • Shiny:从DT数据表中选定的行获取信息

    我们正在尝试重新创建示例 https demo shinyapps io 029 row selection https demo shinyapps io 029 row selection 使用DT包来渲染数据帧而不是shiny包 DT
  • 将模式的所有元素与向量以相同的顺序匹配

    我创建了一个函数yes seq需要两个参数 一个模式pat和数据dat 该函数以相同的顺序查找数据中是否存在模式 例如 dat lt letters 1 10 dat 1 a b c d e f g h i j pat lt c a c g
  • 在ggplot2中,箱线图线的末尾代表什么?

    我找不到箱线图线条端点代表什么的描述 For example here are point values above and below where the lines end 我意识到盒子的顶部和底部是第 25 个和第 75 个百分位数
  • 如何在R中创建for循环? [复制]

    这个问题在这里已经有答案了 可能的重复 如何在 R 编程中启动 for 循环 https stackoverflow com questions 4162363 how to start a for loop in r programmin
  • 如何创建 highcharter 事件函数以在 Shiny R 中创建“下拉函数”

    我正在建造一个shiny应用程序 我想要完成的事情之一是创建一个下拉菜单 我想将劳动力变量绘制为不同级别的年份变量的函数 请参阅下面的示例数据框 year level 2 level 3 labour 1 2013 10 101 1 2 2
  • 基本 dyplr 函数给出错误:“check_dots_used”

    试图找出为什么我会收到此错误 以前从未见过 谷歌没有帮助 check dots used action warn 中的错误 未使用参数 action warn 我在下面的非常基本的试验中收到错误 而且在 group by count 中也收
  • R中具有特定条件的多列变异

    我有这个数据 M1 M2 M3 UCL 1 2 3 1 5 我想在这种情况下创建新列 如果M1大于UCL MM1将为 UP 否则为 NULL 如果M2大于UCL MM2将为 UP 否则为 NULL 如果M3大于UCL MM3将为 UP 否则
  • ggplot 按因子和梯度颜色

    我正在尝试绘制一个对两个变量 一个因子和一个强度 进行着色的图 我希望每个因素都是不同的颜色 并且我希望强度是白色和该颜色之间的渐变 到目前为止 我已经使用了诸如对因子进行分面等技术 将颜色设置为两个变量之间的相互作用 并将颜色设置为因子并
  • 解压 R 数据框中的列表

    我有一个dataframe其中一个字段包含不同长度的列表 我想将该字段中列表的每个元素提取到其自己的字段中 以便我可以将结果收集到一个很长的字段中dataframe每个列表元素都有一个 id 这是一个例子dataframe dat lt s
  • ODE 时间 Matlab 与 R

    如果在 matlab 中使用可变时间步长求解器 例如 ODE45 我会定义输出的时间跨度 即times 0 50 matlab 将返回 0 到 50 之间不同时间步长的结果 然而在 R 中 我似乎必须定义我希望 ODE 返回结果的时间点 即
  • 如何在R中安装pivot_long()和pivot_wide()

    如果您想尝试这些新功能 pivot wide and pivot long 需要安装开发版tidyr devtools install github tidyverse tidyr 但我还没有实现它 我安装了一系列库 除了一个之外 vctr
  • R 中舍入到下一个数量级的算法

    如果标题不清楚 我很抱歉 但我无法简洁地解释它 给定一个浓度向量 我想将最大值四舍五入到下一个数量级 即 345 到 1000 另外 我想将最小值四舍五入到较低的数量级 即 3 2 到 1 这些浓度也可能低于 1 因此例如 0 034 需要
  • 如何编写固定宽度的文件?

    我应该编写一个基于固定宽度列的特定格式的 txt 文件 例如 第 1 8 列中的第一个变量 第 9 15 列中的第二个变量 原始数据有不同的长度 它们必须放在指定列的右侧 例如 值 15 96 和 12 489 必须写入第一行和第二行的第1
  • 如何自动替换多个文件的文本内容中的字符?

    我有一个文件夹 myfolder包含许多乳胶表 我需要替换其中每个字符 即替换任何minus sign by an en dash 只是为了确定 我们正在替换连字符INSIDE该文件夹中的所有 tex 文件 我不关心 tex 文件名 手动执
  • R:使用数据框 A 中某个日期之前的值填充数据框 B 中的行

    这可能非常复杂 我怀疑需要先进的知识 我现在有两种不同类型的 data frames 我需要组合 数据 数据框A 按患者 ID 列出所有输血日期 每次输血均由单独的行表示 患者可以进行多次输血 不同的患者可以在同一天进行输血 Patient
  • 消除垂直线ggplot

    这个问题以前曾被问过 但答案并不总是明确或很复杂 我希望 ggplot2 的新版本能够带来更简单的解决方案 如何仅消除 ggplot 的垂直线而不消除轴刻度线或标签 这对于条形图来说确实很好 因为它可以消除图形中一些不必要的干扰 这里有一些
  • R中的for循环和if函数

    我正在用 R 中的 if 函数编写一个循环 表格如下 ID category 1 a 1 b 1 c 2 a 2 b 3 a 3 b 4 a 5 a 我想使用 for 循环和 if 函数添加另一列来计算每个分组的 ID 如下所示的计数列 I
  • Pyspark - 一次聚合数据帧的所有列[重复]

    这个问题在这里已经有答案了 我想将数据框分组到单个列上 然后对所有列应用聚合函数 例如 我有一个包含 10 列的 df 我希望对第一列 1 进行分组 然后对所有剩余列 均为数字 应用聚合函数 sum 与此等效的 R 是 summarise

随机推荐

  • 什么是右值、左值、x值、左值和右值?

    在 C 03 中 表达式可以是rvalue or an lvalue 在 C 11 中 表达式可以是 rvalue lvalue xvalue glvalue prvalue 两类变成了五类 这些新的表达类别是什么 这些新类别与现有的右值和
  • C++0x中统一初始化,什么时候用()代替{}?

    是否有经验法则来决定何时使用旧语法 而不是新语法 初始化一个结构体 struct myclass myclass int px int py x px y py private int x y myclass object 0 0 现在的情
  • Rails 3.HABTM 表单选择下拉菜单

    我有一张发票表格 这是一个简化版本 因此它具有行项目 您可以在其中选择产品名称的下拉菜单 这运行良好 因此发票 line item 关系是这样的 发票 has many line items 且 line item 属于发票 line it
  • @xmlSchema 注释与 jaxb 一起使用

    我无法在 xml 文件中显示在包级别使用 xmlSchema 注释配置的所有参数 例如 如果我设置 javax xml bind annotation XmlSchema xmlns javax xml bind annotation Xm
  • 提交 Hadoop 作业

    我需要不断获取映射器和减速器的运行时间 我已提交作业如下 JobClient jobclient new JobClient conf RunningJob runjob jobclient submitJob conf TaskRepor
  • 如何将 VScode 设置为 git /macbook 中的核心编辑器[重复]

    这个问题在这里已经有答案了 我无法将 Visual Studio Code 设置为 git 的核心编辑器 当我尝试进行 git 提交时 我只看到编辑器有问题的信息 MacBook Air Agata agataskrzypczyk git
  • 创建带有格式的“git log”别名

    我已经在 bash profile 中设置了一堆可以正常工作的 git 别名 alias gst git status alias gl git pull alias gp git push alias gd git diff mate a
  • 什么时候应该使用 Java 的 StringWriter? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 什么是JavaStringWriter 什么时候应该使用它 我已阅读文档并查看了here http examples javacode
  • 在 ASP.NET 中查找浏览器本地时间

    如何找出用户在 ASP NET 中浏览您的网站的当地时间 创建一个隐藏的输入控件 以在下一页回发时将值返回到服务器 需要在页面的 onload 事件中使用 JavaScript 创建的新 Date 对象的值填充它 您将需要创建一个 Java
  • Python Kivy ListView:如何删除选定的ListItemButton?

    我正在尝试通过构建一个简单的待办事项列表应用程序来学习 kivy 就像 Creating apps in Kivy 一书的作者 Dusty Phillips 所建议的那样 这是到目前为止的代码 from kivy app import Ap
  • 仅恢复推送提交的单个文件

    以下是推送的提交历史记录 Commit Changed Files Commit 1 File a File b File c Commit 2 File a File b File c Commit 3 File a File b Fil
  • 在 SwiftUI 中使用 ForEach 插入、更新和删除动画

    我设法为显示在 a 中的项目提供了一个很好的插入和删除动画ForEach 通过完成 transition on Row 但遗憾的是 当我刚刚更新名称时 也会触发此动画Item在观察到的数组中 当然这是因为它实际上是一个新视图 你可以看到 因
  • 由于 Spannable TextView 导致 java.lang.IllegalArgumentException

    我在 Google Play 控制台中收到了此崩溃报告 但我自己从未经历过且无法重现 java lang IllegalArgumentException at android text method WordIterator checkO
  • Xamarin.Auth 与 Twitter

    我正在尝试实现 Facebook 和 Twitter 登录 我可以在 Facebook 上使用它 但不知道如何在 Twitter 上使用它 有例子吗 我的 Facebook 实现是这样的 var auth new OAuth2Authent
  • 模板类运算符重载问题

    我正在尝试移植一些 Visual C VS2005 代码 以便它可以在 VS2005 和 C Builder XE 下编译 下面的代码在 VS2005 下编译正常 但在 C Builder XE 下 出现以下错误 BCC32 错误 time
  • 正则表达式或其他方式从具有变量条目的行中获取数据

    在 python 中 我试图从一行中获取数据 这些线条看起来像 1 cpasite 5 nsubl 4 cpatypes 3 4 5 6 2 cpasite 6 nsubl 2 cpatypes 7 8 3 cpasite 7 nsubl
  • 我可以读取位于资源文件中的 .ini 文件吗?

    include mainwindow h include ui mainwindow h include
  • MySQL - 从值以逗号分隔的列中选择不同的值

    要从 table1 和 column1 获取不同值的列表就像这样做一样简单 SELECT distinct column1 FROM table1 但是 我继承了 不幸的是 一个数据库 其中 column1 包含用逗号分隔的值 column
  • Web API 可选参数

    我有一个具有以下签名的控制器 Route products filter apc apc xpc xpc sku sku public IHttpActionResult Get string apc string xpc int sku
  • 有效检查 data.table 中其他行的值

    Note 这是我最初发布到 data table 帮助组的一个问题 马特 道尔 Matt Dowle 要求提供更详细的示例 我发布了这个示例 但我在电子邮件格式方面遇到了麻烦 我已经知道如何格式化 SO 所以我想我应该将其发布在这里 我基本