有没有办法在 i 中自我引用 data.table

Posted

技术标签:

【中文标题】有没有办法在 i 中自我引用 data.table【英文标题】:Is there a way to self reference a data.table in i 【发布时间】:2022-01-13 08:13:54 【问题描述】:

考虑标准 data.table 语法DT[i, j, ...]。由于.SD 仅在ji 中的NULL 中定义,是否有任何方法可以隐式(期望)或显式(通过.SD 之类的东西)在函数中引用当前data.table i?

用例

我想编写一个过滤标准列的函数。列名在多个表中是相同的,而且有些冗长。为了通过减少打字来加快我的编码速度,我想写一个这样的函数:

library(data.table)
dt <- data.table(postal_code   = c("USA123", "SPEEDO", "USA421"),
                 customer_name = c("Taylor", "Walker", "Thompson"))
dt
#>    postal_code customer_name
#> 1:      USA123        Taylor
#> 2:      SPEEDO        Walker
#> 3:      USA421      Thompson

# Filter all customers from a common postal code 
# that surname starts with specific letters
extract <- function(x, y, DT) 
  DT[, startsWith(postal_code, x) & startsWith(customer_name, y)]



# does not work
dt[extract("USA", "T", .SD)]
#> Error in .checkTypos(e, names_x): Object 'postal_code' not found.
#>    Perhaps you intended postal_code

# works but requires specifying the data.table explicitly
# plus the drawback that it cannot be called upon, e.g. a grouped .SD
# in a nested call
dt[extract("USA", "T", dt)]
#>    postal_code customer_name
#> 1:      USA123        Taylor
#> 2:      USA421      Thompson

想要的(伪代码)

dt[extract("USA", "T")]
#>    postal_code customer_name
#> 1:      USA123        Taylor
#> 2:      USA421      Thompson

# but also
# subsequent steps in j
dt[extract("USA", "T"), relevant := TRUE][]
#>    postal_code customer_name relevant
#> 1:      USA123        Taylor     TRUE
#> 2:      SPEEDO        Walker       NA
#> 3:      USA421      Thompson     TRUE

# using other data.tables
another_dt[extract("USA", "T")]
yet_another_dt[extract("USA", "T")]

【问题讨论】:

似乎fcase 可以处理您的第二个用例:dt[, relevant := fcase(extract("USA", "T", dt), TRUE, default = NA)][]。您是否有其他 fcase 无法处理的用途? 感谢您的评论。我知道有多种方法可以在j 中产生所需的结果。但是,我真的很想触发i 中的所有内容,因为它更加通用和方便。通常我首先检查过滤的行并随后更新它们。此外,dt[extract("USA", "T"), relevant := TRUE]dt[, relevant := fcase(extract("USA", "T", dt), TRUE, default = NA)] 更易读。它不是关于“我怎样才能得到这个结果”,而是非常具体到“我怎样才能在i 中使用这样的功能。 诚然它不那么可读,但是这个答案中的方法不会提供所需的多功能性吗? ***.com/a/57091155/9463489 仅作记录,我认为这可能是一个相关的(未解决的)问题:New symbol .D to refer to x in i @jblood94 不完全是因为我不得不再次输入dt,我尽量避免。 【参考方案1】:

我不是data.table 专家,但您可以尝试以下解决方法

> dt[,.SD[extract("USA", "T", .SD)]]
   postal_code customer_name
1:      USA123        Taylor
2:      USA421      Thompson

你在j.SD内播放自我参考

【讨论】:

感谢您的回答。但是,仅过滤并不是唯一的用例。我还想将它用于各种i 操作,例如更新。抱歉不够精确。我相应地更新了我的问题【参考方案2】:

这是一种可能的方法...

#create named vector
mystr <- c(postal_code = "USA", customer_name = "T")
#build query text
query <- paste0("grepl(\"^", mystr, "\", ", names(mystr), ")", collapse = " & ")
#eval/parse dynamic text
dt[eval(parse(text = query)), ]
#    postal_code customer_name
# 1:      USA123        Taylor
# 2:      USA421      Thompson

【讨论】:

使用eval(parse(...)) 的好主意。但是,是否有可能将其“隐藏”在extract() 中?在***代码中使用 eval - parse 是不可取的。

以上是关于有没有办法在 i 中自我引用 data.table的主要内容,如果未能解决你的问题,请参考以下文章

data.table 中的内存泄漏按引用分组分配

了解 R 中 data.table 的引用属性

在data.table中具有指定变量的引用列

data.table 中的 dplyr::slice [重复]

使用带有R内核的jupyter笔记本,如何通过引用来抑制打印结果更新data.table?

R:尝试转换 data.table 时出错