2015-04-03 22 views
2

我想創建一個函數「startswith」用於data.table中的括號內,它應該返回一個包含以所提供字符開頭的列名稱的字符向量。例如從括號內退回data.table colulmn名字

DT <- data.table(x=1, y=2, z1=1, z2=2) 
# the syntax DT[, startswith("z")] is equivalent to 
DT[, .(z1, z2)] 
# returns 
    z1 z2 
1: 1 2 

我熟悉grep命令來搜索文本表述,但我無法找到一種方法來從括號內是指DT的列名,一個解決方案,我嘗試是使用ls( )以及與DT相關的環境列出DT中的所有列,但是我還沒有找到從括號內引用此環境的方法。

目標是爲grep創建一個包裝器,以用作便利功能。我不想從括號中指定DT。

+2

也許data.table開發者可以添加一個'.COLNAMES'對象(比如'.I','.BY'等),以便在括號內用於這樣的事情。就我個人而言,我只會做兩行這樣的操作。 – Frank 2015-04-03 17:01:54

回答

4

當然還有一個更慣用的做法,但是這是我想出了:

startswith <- function(pattern = "z") { 

    re <- paste0("^", pattern) 

    call_info <- deparse(sys.calls()[[1]]) 

    if (grepl("(^.+\\()(.+)(\\)$)",call_info)) { 
    this_name <- sub("(^.+\\()(.+)(\\)$)","\\2",call_info) 
    } else { 
    this_name <- strsplit(call_info,"\\[")[[1]][1] 
    } 

    this <- copy(get(this_name)) 
    this_names <- names(this) 

    eval.parent(grep(re,this_names)) 

} 

library(data.table) 
DT <- data.table(x=1, y=2, z1=1, z2=2) 
## 
R> DT[,.(z1, z2)] 
    z1 z2 
1: 1 2 
## 
R> DT[,startswith(), with=F] 
    z1 z2 
1: 1 2 

我不得不在if() {} else {}區塊中添加,以便這可以是你的在功能內部,例如

Foo <- function(gt) { 
    f <- gt[,startswith(),with=F] 
    # {do something interesting with f} 
    f 
} 
## 
R> Foo(DT) 
    z1 z2 
1: 1 2 

我認爲這雖然是一個有趣的問題 - 據我所知,R不具有像the this pointer in C++一個概念,但肯定會是有用的,像這樣的情況。從本質上講,我所有的sys.call,get等hackery都只是讓我可以檢索調用對象的名稱。

+0

不錯的功能。你自己想出來了嗎? – 2015-05-12 12:25:21

+0

爲什麼你使用'copy(get(this_name))'而不是'get(this_name)'? – A5C1D2H2I1M1N2O1R2T1 2015-05-12 12:41:21

+0

@AnandaMahto我想這只是我用'data.table's陷入的一種習慣,因爲有時我並不完全確定在通過引用修改時對本地對象所做的更改是否會傳播到原始'data.table'。儘管在這種情況下,我沒有通過引用進行任何修改,所以您在這裏不需要使用「copy」。 – nrussell 2015-05-12 14:18:47

1

你可以做這樣的,

> DT <- data.table(x=1, y=2, z1=1, z2=2) 
> DT[, grepl("^z", colnames(DT)), with=FALSE] 
    z1 z2 
1: 1 2 
+1

關鍵是要創建一個用於作爲便利功能的grep的包裝器。我不想從括號中指定DT。 – k13 2015-04-03 15:58:43