识别字符串中的第一个匹配位置

时间:2015-03-18 13:17:34

标签: r loops if-statement substring

我有一个字符串(“00010000”),需要确定我们看到第一个“1”的位置。 (这告诉我客户哪个月有效)

我有一个如下所示的数据集:

id  <- c(1:5)
seq <- c("00010000","00001000","01000000","10000000","00010000")
df <- data.frame(id,seq)

我想为每个id创建一个标识first_month_active的新字段。

我可以使用嵌套的ifelse函数手动执行此操作:

    df$first_month_active <-
        ifelse(substr(df$seq,1,1)=="1",1,
        ifelse(substr(df$seq,2,2)=="1",2,
        ifelse(substr(df$seq,3,3)=="1",3,       
        ifelse(substr(df$seq,4,4)=="1",4,
        ifelse(substr(df$seq,5,5)=="1",5,99 ))))) 

这给了我想要的结果:

  id  seq        first_position
  1   00010000   4
  2   00001000   5
  3   01000000   2
  4   10000000   1
  5   00010000   4

但是,对于包含36个月的数据,这不是理想的解决方案。

我想使用带有ifelse语句的循环,但是我真的很难用语法

for (i in 1:36) {
ifelse(substr(df$seq,0+i,0+i)=="1",0+i,
}

非常感谢任何想法

7 个答案:

答案 0 :(得分:12)

或尝试stringi

library(stringi)
stri_locate_first_fixed(df$seq, "1")[, 1]
## [1] 4 5 2 1 4

答案 1 :(得分:10)

跳过循环和ifelse

9 - nchar(as.numeric(seq))
## [1] 4 5 2 1 4

这在您的data.frame中不会起作用,因为您强制seq隐式计算因素,所以只需这样做:

9 - nchar(as.numeric(as.character(df$seq)))
## [1] 4 5 2 1 4

编辑:只是为了好玩,因为弗兰克没有将他的评论转换成答案,这里有strsplit解决方案:

# from original vector
sapply(strsplit(seq, "1"), nchar)[1,] + 1
## [1] 4 5 2 1 4

# from data.frame
sapply(strsplit(as.character(df$seq), "1"), nchar)[1,] + 1
## [1] 4 5 2 1 4

答案 2 :(得分:8)

您可以使用gregexpr

> unlist(gregexpr(pattern=1,seq,fixed=T))
[1] 4 5 2 1 4

答案 3 :(得分:8)

以下可以完成这项工作:

library(stringr)
str_locate(pattern ='1',seq)

答案 4 :(得分:6)

一些比较:

library(stringi)
library(stringr)

seq <- c("00010010","00001000","10000010","10000000","00010000")
seq2 <- rep(seq, 5e6)

system.time(regexpr("1", seq2))
   user  system elapsed 
   4.78    0.03    4.82

system.time(9-nchar(as.numeric(as.character(seq2))))
   user  system elapsed
   34.89    0.18   35.52

system.time(str_locate(pattern ='1',seq2))
   user  system elapsed 
   6.17    0.21    6.53

system.time(stri_locate_first_fixed(seq2, "1")[, 1])
   user  system elapsed
   1.68    0.15    1.84

system.time(nchar(seq2)-round(log10(as.numeric(seq2))))
   user  system elapsed
   7.67    0.09    7.86

system.time(nchar(sub('1.*', '', seq2))+1)
   user  system elapsed
   14.61    0.11   14.93

答案 5 :(得分:3)

另一个,使用log

  nchar(seq)-round(log10(as.numeric(seq)))

答案 6 :(得分:3)

使用sub

的另一个选项
nchar(sub('1.*', '', seq))+1
#[1] 4 5 2 1 4