如何在data.table上运行apply?

Mai*_*ura 32 r apply data.table

我有一个第data.table2列到第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," ","_") }))
Run Code Online (Sandbox Code Playgroud)

或者如果我把它作为一个data.table对象,那么我可以一次一行:

dt[,SpeciesName := str_replace(SpeciesName, " ", "_")
Run Code Online (Sandbox Code Playgroud)

我如何对所有列2到最后类似于上面的那个?

Jos*_*ien 34

在2015-11-24完全重写,修复以前版本中的错误.

你有几个选择.

  1. 使用嵌入式调用处理所有目标列 lapply(),使用:=分配修改后的值.这依赖:=于对其LHS上命名的多个列的同时分配的非常方便的支持.

  2. 使用for循环一次一个地遍历目标列,使用set()依次修改每个列的值.

  3. 使用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[, .SDcols=cnames[-1L], cnames[-1L] := 
  lapply(.SD, function(x) gsub(" ", "_", x, fixed=TRUE)), ]
})
##   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]], fixed=TRUE))
    }
})
##   user  system elapsed 
##  10.65    0.05   10.70 

## Method 3
system.time({
    for(cname in cnames[-1]) {
        DT3[ , (cname) := gsub(" ", "_", get(cname), fixed=TRUE)]
    }
})
##   user  system elapsed 
##  10.33    0.03   10.37 
Run Code Online (Sandbox Code Playgroud)

有关详细信息set(),并:=阅读他们的帮助页面,通过输入得到?set?":=".


flo*_*del 7

你可以这样做:

library("stringr")
dt[, -1] <- lapply(dt[, -1], function(x) str_replace(x," ","_"))
Run Code Online (Sandbox Code Playgroud)