【问题标题】:Using gsub adding new column in a data.table使用 gsub 在 data.table 中添加新列
【发布时间】:2015-05-13 15:02:17
【问题描述】:

对不起,一个非常基本的问题,解决方案一定很简单,但我找不到。

尝试使用 gsub 在 data.table 中添加新列时,我收到了警告 “参数 'replacement' 的长度 > 1,并且只会使用第一个元素”,并且所有 data.table 行在新列中都有第一行的值。

这里是一个简化的例子:

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

新列 v3 在所有行中都包含一个带有“1”而不是“x”的字符串。

使用其他功能,例如

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

按预期工作。

我正在使用 Rstudio v.0.98.1103、R v.3.1.2、data.table v.1.9.4

【问题讨论】:

  • gsub 在替换中没有矢量化,所以这就是警告告诉你的。
  • 另一个选项是myFunc &lt;- function(x, y) gsub("x", x, y) ; dt[ , v3 := mapply(myFunc, v1, v2)] 。另外,在我的编辑中,当您使用:= 运算符时,它正在更新数据,因此无需使用dt &lt;- dt 再次重新分配它。请查看here 了解更多信息。
  • @DavidArenburg :感谢您的评论,即使更新到位,我也习惯于重新分配数据表,因为我发现在执行过程中,在控制台中看到所有头/更新数据表的尾部(更难发现错误/警告)。也许有更聪明的方法来避免它......

标签: r data.table


【解决方案1】:
dt[, v3 := gsub("x", v1, v2), by = v1]  

【讨论】:

  • 聪明。我猜也可以是1:nrow(dt)。 +1
  • @AnandaMahto 我想如果有任何重复值(与 OP 中不同),效率会降低,例如,dt &lt;- data.table(v1=c(1L,1:3),v2=paste0(c("a",letters[1:3]),"x"))
  • @AnandaMahto:谢谢,我更喜欢你的 'by' 因为 'by=v1' 工作正常,但给出了我提到的相同警告(“argument 'replacement' has length > 1 and only the first元素将被使用")
  • 这很奇怪,我在by=v1时没有收到任何警告
  • @QuinnWeber - 我明白了:根据我的真实数据,v1 没有唯一值。为避免警告,“by”必须一次获取 1 行(所以我认为,出于性能目的,最好使用带有矢量化参数的函数,如其他答案中所建议的那样)
【解决方案2】:

最简单的方法是使用具有矢量化参数的字符串处理包,例如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

或者,您可以使用Vectorize 函数制作自己的“矢量化”版本的gsub

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

【讨论】:

  • 最新的 stringr 包现在由 stringi 提供支持。你可以做 library(stringr) dt[ , v3:=str_replace(v2,"x",v1)]
猜你喜欢
  • 2014-08-11
  • 2014-01-30
  • 2020-07-29
  • 1970-01-01
  • 2017-06-22
  • 1970-01-01
  • 2021-11-27
  • 2018-11-25
  • 1970-01-01
相关资源
最近更新 更多