Подтвердить что ты не робот

Как запустить приложение на таблице данных?

У меня есть data.table со столбцами с 2 по 20 как строки с пробелами (например, "Имя видов" ). Я хочу запустить str_replace() во всех этих столбцах одновременно, чтобы все "Имя видов" стали "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 до конца, аналогичных одному из вышеперечисленных?

4b9b3361

Ответ 1

Полностью переписано 2015-11-24, чтобы исправить ошибку в предыдущих версиях.

Также добавлены более современные опции на 2019-09-27

У вас есть несколько вариантов.

  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 

Для получения более подробной информации о set() и := прочитайте их страницу помощи, которую можно получить, набрав ?set или ?":=".

Ответ 2

Вы можете сделать это:

library("stringr")
dt[, -1] <- lapply(dt[, -1], function(x) str_replace(x," ","_"))