使用stringr中的str_sub替换向量的所有元素中的字符

时间:2012-11-02 18:12:23

标签: r

我正在尝试替换字符串向量的所有元素中的字符,其中字符不同,但始终与字符串的开头或结尾有一定距离。我可以成功使用substr来替换字符串开头的字符。我试图使用包str_sub中的stringr来替换sting末尾的字符(因为它允许向后计数负数)。它替换了字符,但是对于第一个元素之后的所有元素,它将字符右边的所有元素替换为第一个元素的字符串结尾:

> require(stringr)
> x <- c("A'B'C","E!FG@H","I$JKL&M")
> substr(x,2,2) <- ":"
> x
[1] "A:B'C"   "E:FG@H"  "I:JKL&M"
> str_sub(x,-2,-2) <- ":"
> x
[1] "A:B:C"   "E:FG:C"  "I:JKL:C"

2 个答案:

答案 0 :(得分:6)

试试这个:

require(stringr)
x <- c("A'B'C","E!FG@H","I$JKL&M")
substr(x,2,2) <- ":"
str_sub(x, rep(-2, length(x)),  rep(-2, length(x))) <- ":"

它的行为是因为str_sub<-str_sub(x, start, end)的结果传递给str_c,这就是崩溃对你来说错误的地方。

源代码中的函数是:

"str_sub<-" <- function(string, start = 1L, end = -1L, value) {
     str_c(
        str_sub(string, end = start - 1L),
        value,
        ifelse(end == -1L, "", str_sub(string, start = end + 1L)))
 }

所以我们实际上将三个参数传递给str_c函数,一个或多个字符向量,一个插入字符串和一个折叠参数(ifelse位)。如果不使用赋值函数只运行str_sub的结果是(如果我们已经运行了第一个str_sub:

> (test.string <- str_sub(x, start = 1L, end = -2 - 1L)) #start defaults to 1L
[1] "A:B"   "E:FG"  "I:JKL"
> replace.string <- ":"
> (collapse.string <- ifelse(end == -1L, "", str_sub(string, start = end + 1L)))
[1] "C"
> str_c(test.string, replace.string, collapse.string)
[1] "A:B:C"   "E:FG:C"  "I:JKL:C"

首先,我们将所有要替换的符号左侧的所有内容保存,然后我们重新设置折叠参数。折叠参数有点有趣,如果你看一下str_c的文档,你会发现它说的是

  

如果折叠是......非''NULL',则在每行的末尾插入该字符串,并将整个矩阵折叠为单个字符串。

这就是这里发生的事情,当我们替换字符串时,它会将collapse参数添加到每个字符串的末尾。

但实际上,如果没有使用ifelse函数,这将有效,因为如果没有ifelse,str_sub(string, start = end + 1L)将返回[1] "C" "H" "M"而不是仅仅取第一个索引,&#34; C& #34 ;.

所以这就是为什么当我们添加c(-2,-2,-2)的开始和结束值时,我们可以得到正确的答案:

> (test.string <- str_sub(x, start = 1L, end = c(-2, -2, -2) - 1L)) #start defaults to 1L
[1] "A:B"   "E:FG"  "I:JKL"
> replace.string <- ":"
> (collapse.string <- ifelse(end == -1L, "", str_sub(string, start = c(-2, -2, -2) + 1L)))
[1]  "C" "H" "M"
> str_c(test.string, replace.string, collapse.string)
[1] "A:B:C"   "E:FG:C"  "I:JKL:C"

答案 1 :(得分:1)

不确定str_sub的问题是什么,但你可以自己动手:

my_sub <- function(x,n,s) {
  N <- nchar(x)-n+1
  substr(x,n,n) <- substr(x,N,N) <- s
  x 
}
my_sub(x,2,":")
# [1] "A:B:C"   "E:FG:H"  "I:JKL:M"