我有一个data.table
,其中第2列到第20列是带空格的字符串(例如,“物种名称”)。我想同时在所有这些列上运行str_replace()
,因此所有“Species Name”都变为“Species_Name”。我可以这样做:
data.table(apply(as.data.frame(dt[,2:dim(dt)[2], with=F]), 2,
function(x){ str_replace(x," ","_") }))
或者如果我将其保留为data.table
个对象,那么我可以一次执行此列:
dt[,SpeciesName := str_replace(SpeciesName, " ", "_")
如何对所有第2列到最后一行执行此操作?类似于上面的那个?
答案 0 :(得分:32)
在2015-11-24完全重写,修复以前版本中的错误。
您有几个选择。
使用嵌入式调用处理所有目标列
lapply()
,使用:=
分配修改后的值。这个
依靠:=
非常方便的支持同时分配到其LHS上命名的几个列。
使用for
循环一次一个地运行目标列,
使用set()
依次修改每个值。
使用for
循环迭代多个"天真"电话
到[.data.table()
,每个修改一列。
这些方法似乎都同样快,所以你使用哪种方法 主要是品味问题。 (1)非常紧凑 表现力。它是我经常使用的,尽管你可能会发现(2) 更容易阅读。因为他们一次一个地处理和修改列,所以(2)或(3)将在极少数情况下具有优势,在这种情况下,您的data.table非常大,以至于您有可能遇到限制 由你的R会议的可用记忆强加的。
library(data.table)
## Create three identical 1000000-by-20 data.tables
DT1 <- data.table(1:1e6,
as.data.table(replicate(1e6, paste(sample(letters, nr, TRUE),
sample(letters, nr, TRUE)))))
cnames <- c("ID", paste0("X", 1:19))
setnames(DT1, cnames)
DT2 <- copy(DT1); DT3 <- copy(DT1)
## Method 1
system.time({
DT1[, cnames[-1] := lapply(DT1[,cnames[-1],with=FALSE],
function(x) gsub(" ", "_", x))]
})
## user system elapsed
## 10.90 0.11 11.06
## Method 2
system.time({
for(cname in cnames[-1]) {
set(DT2, j=cname, value=gsub(" ", "_", DT2[[cname]]))
}
})
## user system elapsed
## 10.65 0.05 10.70
## Method 3
system.time({
for(cname in cnames[-1]) {
DT3[ , cname := gsub(" ", "_", DT3[[cname]]), with=FALSE]
}
})
## user system elapsed
## 10.33 0.03 10.37
有关set()
和:=
的详细信息,请阅读他们的帮助页面,点击?set
或?":="
即可获得。
答案 1 :(得分:7)
你可以这样做:
library("stringr")
dt[, -1] <- lapply(dt[, -1], function(x) str_replace(x," ","_"))