在data.table R中选择列的子集

Jef*_*eff 46 r data.table

我有一个包含一堆列的数据表,例如:

dt<-data.table(matrix(runif(10*10),10,10))
Run Code Online (Sandbox Code Playgroud)

我想对数据表执行一些操作,例如生成相关矩阵(cor(dt)).为此,我想删除一些包含非数字值或某个范围之外的值的列.

假设我想找到不包括V1,V2,V3和V5的相关矩阵.

这是我目前的做法:

cols<-!(colnames(dt)=="V1" | colnames(dt)=="V2" | colnames(dt)=="V3" | colnames(dt)=="V5")
new_dt<-subset(dt,,cols)
cor(new_dt)
Run Code Online (Sandbox Code Playgroud)

考虑到data.table语法通常很优雅,我发现这非常麻烦.有没有更好的方法呢?

Aru*_*run 72

用途with=FALSE:

cols = paste("V", c(1,2,3,5), sep="")

dt[, !cols, with=FALSE]
Run Code Online (Sandbox Code Playgroud)

我建议通过"data.table简介"小插图.


更新:从此以后v1.10.2,您还可以:

dt[, ..cols]
Run Code Online (Sandbox Code Playgroud)

请参阅第一条新闻下v1.10.2的在这里的附加说明.

  • 要避免使用`with = FALSE',你也可以像这样使用.SD:`dt [,.SD,.SDcols = cols]`它将返回你放在`cols`中的列定义的数据子集.我发现这更容易以编程方式实现. (8认同)
  • 对不起 - 意在澄清这对我来说更容易记住.我永远不会记得什么时候必须引用它们,什么时候不引用,因此何时使用`with = FALSE`以及何时不使用.我发现这个代码比使用`with = FALSE'更具可读性,因为我不必记住为什么我"关闭"data.table的一个很好的功能 - 不必引用列名. (7认同)
  • 我懂了。它与基础 R 中的“with()”非常相似,如果有帮助的话。我知道 `.SDcols` 对您来说很方便,这很好。虽然我不禁感觉到,由于某种原因,最近在 R 编程中,尤其是在 data.table 和 dplyr 语法方面,*可读性*的问题是通过放大镜来看待的。 (2认同)

MrF*_*ick 15

你可以做

dt[, !c("V1","V2","V3","V5"), with=FALSE]
Run Code Online (Sandbox Code Playgroud)

要得到

            V4         V6         V7        V8         V9        V10
 1: 0.88612076 0.94727825 0.50502208 0.6702523 0.24186706 0.96263313
 2: 0.11121752 0.13969145 0.19092645 0.9589867 0.27968190 0.07796870
 3: 0.50179822 0.10641301 0.08540322 0.3297847 0.03643195 0.18082180
 4: 0.09787517 0.07312777 0.88077548 0.3218041 0.75826099 0.55847774
 5: 0.73475574 0.96644484 0.58261312 0.9921499 0.78962675 0.04976212
 6: 0.88861117 0.85690337 0.27723130 0.3662264 0.50881663 0.67402625
 7: 0.33933983 0.83392047 0.30701697 0.6138122 0.85107176 0.58609504
 8: 0.89907094 0.61389815 0.19957386 0.3968331 0.78876682 0.90546328
 9: 0.54136123 0.08274569 0.25190790 0.1920462 0.15142604 0.12134807
10: 0.36511064 0.88117171 0.05730210 0.9441072 0.40125023 0.62828674
Run Code Online (Sandbox Code Playgroud)


Jef*_*eff 10

另一种使用方法with=FALSE是使用.SDcols

cols = paste("V", c(1,2,3,5), sep="")
dt[, .SD, .SDcols=-cols]
Run Code Online (Sandbox Code Playgroud)

  • 如果你曾经``paste()`和`sep =""`,你可以使用`paste0()`来保存一些(= 7)键击:) (7认同)

42-*_*42- 6

这似乎是一个改进:

> cols<-!(colnames(dt) %in% c("V1","V2","V3","V5"))
> new_dt<-subset(dt,,cols)
> cor(new_dt)
            V4          V6          V7          V8         V9         V10
V4   1.0000000  0.14141578 -0.44466832  0.23697216 -0.1020074  0.48171747
V6   0.1414158  1.00000000 -0.21356218 -0.08510977 -0.1884202 -0.22242274
V7  -0.4446683 -0.21356218  1.00000000 -0.02050846  0.3209454 -0.15021528
V8   0.2369722 -0.08510977 -0.02050846  1.00000000  0.4627034 -0.07020571
V9  -0.1020074 -0.18842023  0.32094540  0.46270335  1.0000000 -0.19224973
V10  0.4817175 -0.22242274 -0.15021528 -0.07020571 -0.1922497  1.00000000
Run Code Online (Sandbox Code Playgroud)

这个不太容易掌握,但可能适用于需要通过数字向量指定列的情况:

subset(dt, , !grepl(paste0("V", c(1:3,5),collapse="|"),colnames(dt) ))
Run Code Online (Sandbox Code Playgroud)