2012-02-10 1 views
28

У меня есть 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 через конец, подобный одному из вышеперечисленных?

ответ

30

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

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

  1. процесс всех целевых столбцов с встроенным вызовом lapply(), используя := для назначения измененных значений на месте. Это полагается на очень удобную поддержку := для одновременного назначения нескольким столбцам с именем LHS.

  2. Используйте for цикл для запуска через целевых столбцов по одному за раз, используя set(), чтобы изменить значение каждого из них в свою очередь.

  3. Используйте for цикл для перебора несколько «наивным» называет к [.data.table(), каждый из которых изменяет один столбец.

Все эти методы кажутся примерно одинаково быстро, поэтому какой из них вы используете, будет быть в основном дело вкуса. (1) красиво компактный и выразительный. Это то, что я чаще всего использую, хотя вы можете найти (2) легче читать. Поскольку они обрабатывают и изменяют столбцы по одному, (2) или (3) будут иметь преимущество в редкой ситуации, когда ваша таблица данных настолько велика, что вы рискуете столкнуться с ограничениями , наложенными вашим 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 или ?":=".

+0

Это интересный случай. Здесь 19 столбцов из 20 заменяются; RHS ': =' - это почти вся таблица. Преимущество ': =' больше, когда, скажем, один или два столбца добавляются к 20, или изменяется один или два столбца из 20. В тех случаях большая часть столбцов остается на месте, а ': =' намного быстрее, чем копирование всей таблицы. –

+0

Кроме того, 'set()' - это новая функция в v1.8.0 (еще не включенная в CRAN), которая напрямую выполняет функцию ': ='. 'set()' может быть намного быстрее, чем ': =' при назначении в цикле (для более простого более естественного программирования). В последней новости на домашней странице есть пример. –

+1

@MatthewDowle - Спасибо за ваши комментарии.Они напомнили мне, что в уик-энд у меня появилось ошеломляющее чувство ответа, которое я дал здесь, и подтолкнуло меня к пересмотру. Очевидно, у меня были веские причины чувствовать себя ворчащими. Пожалуйста, взгляните на мой пересмотренный ответ. Также **, пожалуйста, добавьте любые предложения, которые у вас есть в ваших комментариях к тексту моего ответа **, где вы думаете, что они могут помочь. Я посмотрю на 'set()', но пока не чувствую себя готовым обсудить это. И еще раз, спасибо за всю работу, которую вы вложили в продолжение разработки пакета data.table! –

6

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

library("stringr") 
dt[, -1] <- lapply(dt[, -1], function(x) str_replace(x," ","_")) 
Смежные вопросы