Select 列 data.table 基于正则表达式
Select columns of data.table based on regex
如何根据正则表达式 data.table 的 select 列?
考虑一个简单的例子如下:
library(data.table)
mydt <- data.table(foo=c(1,2), bar=c(2,3), baz=c(3,4))
有没有办法根据正则表达式使用数据table中的bar
和baz
列?我知道以下解决方案有效,但如果 table 更大并且我想选择更多变量,这很容易变得麻烦。
mydt[, .(bar, baz)]
我想在 dplyr::select()
中加入类似 matches()
的内容,但仅供参考。
大卫的回答有效。但是,如果您的正则表达式很长并且您希望先完成它,请尝试:
cols <- grep("<regex pattern>", names(mydt), value=T)
mydt[, cols, with=FALSE]
这取决于您的喜好和需求。如果您需要完整的原始数据,您还可以将子集 table 分配给选定的变量。
"data.table" 也有一个 subset
方法,因此您可以随时使用如下内容:
subset(mydt, select = grep("bar|baz", names(mydt)))
# bar baz
# 1: 2 3
# 2: 3 4
为 "data.table" 创建 startswith
类型的函数并不是很简单。
您也可以尝试使用 data.table
包中的 %like%
,这是一个 "convenience function for calling regexpr"。但是使代码更具可读性;)
在这种情况下,回答您的问题:
mydt[, .SD, .SDcols = names(mydt) %like% "bar|baz"]
作为 %like%
returns 逻辑向量,可以使用以下内容获取除包含 "foo" 的列之外的每一列:
mydt[, .SD, .SDcols = ! names(mydt) %like% "foo"]
其中 !
否定逻辑向量。
更新: 我更新了与@sindri_baldur 的回答的比较 - 使用版本 1.12.6
。根据结果,patterns()
是一种方便的快捷方式,但如果性能很重要,则应坚持使用 ..
或 with = FALSE
解决方案(见下文)。
显然,从 1.10.2 版本开始有一种新方法可以实现这一点。
library(data.table)
cols <- grep("bar|baz", names(mydt), value = TRUE)
mydt[, ..cols]
它似乎是已发布解决方案中运行速度最快的。
# Creating a large data.table with 100k rows, 32 columns
n <- 100000
foo_cols <- paste0("foo", 1:30)
big_dt <- data.table(bar = rnorm(n), baz = rnorm(n))
big_dt[, (foo_cols) := rnorm(n)]
# Methods
subsetting <- function(dt) {
subset(dt, select = grep("bar|baz", names(dt)))
}
usingSD <- function(dt) {
dt[, .SD, .SDcols = names(dt) %like% "bar|baz"]
}
usingWith <- function(dt) {
cols <- grep("bar|baz", names(dt), value = TRUE)
dt[, cols, with = FALSE]
}
usingDotDot <- function(dt) {
cols <- grep("bar|baz", names(dt), value = TRUE)
dt[, ..cols]
}
usingPatterns <- function(dt) {
dt[, .SD, .SDcols = patterns("bar|baz")]
}
# Benchmark
microbenchmark(
subsetting(big_dt), usingSD(big_dt), usingWith(big_dt), usingDotDot(big_dt), usingPatterns(big_dt),
times = 5000
)
#Unit: microseconds
# expr min lq mean median uq max neval
# subsetting(big_dt) 430 759 1672 1309 1563 82934 5000
# usingSD(big_dt) 547 951 1872 1461 1797 60357 5000
# usingWith(big_dt) 278 496 1331 1112 1304 62656 5000
# usingDotDot(big_dt) 289 483 1392 1117 1344 55878 5000
# usingPatterns(big_dt) 596 1019 1984 1518 1913 120331 5000
自 data.table v1.12.0
(2019 年 1 月)起,您可以:
mydt[, .SD, .SDcols = patterns("bar|baz")]
来自官方文档?data.table
,关于.SDcols
参数:
[...] you can filter columns to include in .SD
based on their names according to regular
expressions via .SDcols=patterns(regex1, regex2, ...)
. The included
columns will be the intersection of the columns identified by each
pattern; pattern unions can easily be specified with |
in a regex. [...] You
can also invert a pattern as usual with .SDcols = !patterns(...)
.
为了提高可读性和性能,我建议使用这种单行代码。
mydt[,names(mydt) %like% "bar|baz", with=F]
关注@Janosdivenji 的回答:
请参阅最后一行 usingLike
Unit: microseconds
expr min lq mean median uq max neval
subsetting(big_dt) 370.582 977.2760 1194.875 1016.4340 1096.9285 25750.94 5000
usingSD(big_dt) 554.330 1084.8530 1352.039 1133.4575 1226.9060 189905.39 5000
usingWith(big_dt) 238.481 832.7505 1017.051 866.6515 927.8460 22717.83 5000
usingDotDot(big_dt) 256.005 844.8770 1101.543 878.9935 936.6040 181855.43 5000
usingPatterns(big_dt) 569.787 1128.0970 1411.510 1178.2895 1282.2265 177415.23 5000
usingLike(big_dt) 262.868 852.5805 1059.466 887.3455 948.6665 23971.70 5000
如何根据正则表达式 data.table 的 select 列? 考虑一个简单的例子如下:
library(data.table)
mydt <- data.table(foo=c(1,2), bar=c(2,3), baz=c(3,4))
有没有办法根据正则表达式使用数据table中的bar
和baz
列?我知道以下解决方案有效,但如果 table 更大并且我想选择更多变量,这很容易变得麻烦。
mydt[, .(bar, baz)]
我想在 dplyr::select()
中加入类似 matches()
的内容,但仅供参考。
大卫的回答有效。但是,如果您的正则表达式很长并且您希望先完成它,请尝试:
cols <- grep("<regex pattern>", names(mydt), value=T)
mydt[, cols, with=FALSE]
这取决于您的喜好和需求。如果您需要完整的原始数据,您还可以将子集 table 分配给选定的变量。
"data.table" 也有一个 subset
方法,因此您可以随时使用如下内容:
subset(mydt, select = grep("bar|baz", names(mydt)))
# bar baz
# 1: 2 3
# 2: 3 4
startswith
类型的函数并不是很简单。
您也可以尝试使用 data.table
包中的 %like%
,这是一个 "convenience function for calling regexpr"。但是使代码更具可读性;)
在这种情况下,回答您的问题:
mydt[, .SD, .SDcols = names(mydt) %like% "bar|baz"]
作为 %like%
returns 逻辑向量,可以使用以下内容获取除包含 "foo" 的列之外的每一列:
mydt[, .SD, .SDcols = ! names(mydt) %like% "foo"]
其中 !
否定逻辑向量。
更新: 我更新了与@sindri_baldur 的回答的比较 - 使用版本 1.12.6
。根据结果,patterns()
是一种方便的快捷方式,但如果性能很重要,则应坚持使用 ..
或 with = FALSE
解决方案(见下文)。
显然,从 1.10.2 版本开始有一种新方法可以实现这一点。
library(data.table)
cols <- grep("bar|baz", names(mydt), value = TRUE)
mydt[, ..cols]
它似乎是已发布解决方案中运行速度最快的。
# Creating a large data.table with 100k rows, 32 columns
n <- 100000
foo_cols <- paste0("foo", 1:30)
big_dt <- data.table(bar = rnorm(n), baz = rnorm(n))
big_dt[, (foo_cols) := rnorm(n)]
# Methods
subsetting <- function(dt) {
subset(dt, select = grep("bar|baz", names(dt)))
}
usingSD <- function(dt) {
dt[, .SD, .SDcols = names(dt) %like% "bar|baz"]
}
usingWith <- function(dt) {
cols <- grep("bar|baz", names(dt), value = TRUE)
dt[, cols, with = FALSE]
}
usingDotDot <- function(dt) {
cols <- grep("bar|baz", names(dt), value = TRUE)
dt[, ..cols]
}
usingPatterns <- function(dt) {
dt[, .SD, .SDcols = patterns("bar|baz")]
}
# Benchmark
microbenchmark(
subsetting(big_dt), usingSD(big_dt), usingWith(big_dt), usingDotDot(big_dt), usingPatterns(big_dt),
times = 5000
)
#Unit: microseconds
# expr min lq mean median uq max neval
# subsetting(big_dt) 430 759 1672 1309 1563 82934 5000
# usingSD(big_dt) 547 951 1872 1461 1797 60357 5000
# usingWith(big_dt) 278 496 1331 1112 1304 62656 5000
# usingDotDot(big_dt) 289 483 1392 1117 1344 55878 5000
# usingPatterns(big_dt) 596 1019 1984 1518 1913 120331 5000
自 data.table v1.12.0
(2019 年 1 月)起,您可以:
mydt[, .SD, .SDcols = patterns("bar|baz")]
来自官方文档?data.table
,关于.SDcols
参数:
[...] you can filter columns to include in
.SD
based on their names according to regular expressions via.SDcols=patterns(regex1, regex2, ...)
. The included columns will be the intersection of the columns identified by each pattern; pattern unions can easily be specified with|
in a regex. [...] You can also invert a pattern as usual with.SDcols = !patterns(...)
.
为了提高可读性和性能,我建议使用这种单行代码。
mydt[,names(mydt) %like% "bar|baz", with=F]
关注@Janosdivenji 的回答:
请参阅最后一行 usingLike
Unit: microseconds
expr min lq mean median uq max neval
subsetting(big_dt) 370.582 977.2760 1194.875 1016.4340 1096.9285 25750.94 5000
usingSD(big_dt) 554.330 1084.8530 1352.039 1133.4575 1226.9060 189905.39 5000
usingWith(big_dt) 238.481 832.7505 1017.051 866.6515 927.8460 22717.83 5000
usingDotDot(big_dt) 256.005 844.8770 1101.543 878.9935 936.6040 181855.43 5000
usingPatterns(big_dt) 569.787 1128.0970 1411.510 1178.2895 1282.2265 177415.23 5000
usingLike(big_dt) 262.868 852.5805 1059.466 887.3455 948.6665 23971.70 5000