2015-05-13 5 views
4

Извините за очень простой вопрос, решение должно быть очень простым, но я не могу его найти.Использование gsub добавления нового столбца в data.table

Попытки использовать GSUB добавить новый столбец в data.table, я получил предупреждение «аргумента„замена“имеет длину> 1 и только первый элемент будет использоваться», и все data.table строки имеют в новом столбце значение первой строки.

Вот упрощенный случай:

dt <- data.table(v1=c(1,2,3) , v2=c("axb","cxxd","exfxgx")) 
dt[ , v3:=gsub("x",v1,v2)] 

Новый столбец v3 содержит строку с «1» вместо «х» во всех строках.

Использование других функций, например.

dt[ , v3:=paste(v1,v2)] 

работает должным образом.

Я использую Rstudio v.0.98.1103, R v.3.1.2, data.table v.1.9.4

+5

'gsub' не имеет векторизации в замене, так что предупреждение вам сообщает. – A5C1D2H2I1M1N2O1R2T1

+2

Другим вариантом будет 'myFunc <- function (x, y) gsub (" x ", x, y); dt [, v3: = mapply (myFunc, v1, v2)] '. Кроме того, re my edit, когда вы используете оператор ': =', обновляет данные, поэтому нет необходимости переназначать его снова, используя 'dt <- dt'. Посмотрите [здесь] (https://rawgit.com/wiki/Rdatatable/data.table/vignettes/datatable-reference-semantics.html) для получения дополнительной информации. –

+0

@DavidArenburg: спасибо за ваш комментарий, я привык переназначать таблицу данных, даже если обновление на месте, потому что во время выполнения я нахожу очень раздражающим, чтобы видеть на консоли все главы/хвосты обновленных таблиц данных (это более сложно заметить ошибки/предупреждения). Может быть, есть более умные способы избежать этого ... – mbranco

ответ

5

Самого простой подход будет использовать пакет обработки строки, которая имеет векторизованные аргументы, как stringi:

library(stringi) 
dt[, v3 := stri_replace_all_fixed(v2, "x", v1)][] 
# v1  v2  v3 
# 1: 1 axb a1b 
# 2: 2 cxxd c22d 
# 3: 3 exfxgx e3f3g3 

в качестве альтернативы, вы можете сделать свой собственный "векторизованную" версию gsub с помощью Vectorize функции:

vGsub <- Vectorize(gsub, vectorize.args = c("replacement", "x")) 
dt[, v3 := vGsub("x", v1, v2)][] 
# v1  v2  v3 
# 1: 1 axb a1b 
# 2: 2 cxxd c22d 
# 3: 3 exfxgx e3f3g3 
+0

последний пакет stringr теперь питается от stringi. вы можете сделать библиотеку (stringr) dt [, v3: = str_replace (v2, "x", v1)] – Henk

11
dt[, v3 := gsub("x", v1, v2), by = v1] 
+0

Умный. Также может быть '1: nrow (dt)', я думаю. +1 – A5C1D2H2I1M1N2O1R2T1

+1

@AnandaMahto Я думаю, что это менее эффективно, если есть какие-либо повторяющиеся значения (в отличие от OP), например, 'dt <- data.table (v1 = c (1L, 1: 3), v2 = paste0 (c («a», буквы [1: 3]), «x»)) ' – Frank

+0

@AnandaMahto: спасибо, я предпочитаю ваш« by », потому что« by = v1 »отлично работает, но дает то же предупреждение, о котором я упомянул (" аргумент «замена» имеет длину> 1, и будет использоваться только первый элемент ») – mbranco