有没有办法在 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
仅在j
和i
中的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 中的 dplyr::slice [重复]