2015-05-12 26 views
9

如何根據正則表達式選擇data.table的列? 考慮一個簡單的例子如下:基於正則表達式選擇data.table的列

library(data.table) 
mydt <- data.table(foo=c(1,2), bar=c(2,3), baz=c(3,4)) 

有沒有辦法使用的barbaz列基於正則表達式的數據表的方法嗎?我知道下面的解決方案可行,但如果表格更大,我想選擇更多的變量,這可能很容易變得麻煩。

mydt[, .(bar, baz)] 

我想有像matches()dplyr::select()但只能作爲參考。

+3

你可以做'mydt [,grep的(C( 「欄|巴茲」),名(mydt)),與= FALSE]'但是我想'with'創建一個副本。 –

+0

可能會有所幫助:http://stackoverflow.com/q/13383840和http://stackoverflow.com/q/12603890 – shadowtalker

+0

@DavidArenburg不要以爲它會創建一個副本。 – nicola

回答

3

顯然,從版本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] 
} 

# Benchmark 
microbenchmark(
    subsetting(big_dt), usingSD(big_dt), usingWith(big_dt), usingDotDot(big_dt), 
    times = 5000 
) 

#Unit: microseconds 
#    expr min lq mean median  uq max neval 
# subsetting(big_dt) 462.2 596.2 1383 680.0 1176.8 62292 5000 
#  usingSD(big_dt) 459.8 583.7 1279 669.5 1172.7 57934 5000 
# usingWith(big_dt) 386.6 493.6 1209 572.6 1039.0 61313 5000 
# usingDotDot(big_dt) 364.1 464.6 1063 538.1 945.5 67741 5000 
+0

從data.table [news](https://cran.r-project.org/web/packages/data.table/news.html):「當j是以'..'爲前綴的符號時,它將是(...)在所有操作系統中認爲一級目錄像目錄「..」,意思是父目錄(...)它是實驗性的「。 – janosdivenyi

7

大衛的答案將工作。但是,如果你的正則表達式是漫長的,你寧願它做到第一,嘗試:

cols <- grep("<regex pattern>", names(mydt), value=T) 
mydt[, cols, with=FALSE] 

這只是取決於你的喜好和需求。如果您需要原始的完整版,您也可以將子集表分配給選定的變量。

6

還爲「data.table」一subset方法,讓你隨時可以使用類似以下內容:

subset(mydt, select = grep("bar|baz", names(mydt))) 
# bar baz 
# 1: 2 3 
# 2: 3 4 

turns out,創造一個startswith類型爲「data.table」功能不是很直接。

+0

嗯,我想知道爲什麼OP更喜歡這個'mydt [,grep(c(「bar | baz」),names(mydt)),with = FALSE] –

+0

@DavidArenburg,它稍微快一點? – A5C1D2H2I1M1N2O1R2T1

+0

你測試過了嗎?會有趣的發現。我從來沒有在我的生活中使用過「子集」,但如果速度更快,我可能會給它一個機會。 –

18

您也可以嘗試使用data.table包中的%like%,這是一個「調用regexpr的便捷函數」。然而,使代碼更易讀;)

在這種情況下,回答你的問題:

mydt[, .SD, .SDcols = names(mydt) %like% "bar|baz"] 

由於%like%返回一個邏輯向量,磨片可以使用以下方法來獲取每列除了那些含有「富」:

mydt[, .SD, .SDcols = ! names(mydt) %like% "foo"] 

其中!否定邏輯向量。