Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 标识字符串中的第一个匹配位置_R_Loops_If Statement_Substring - Fatal编程技术网

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

R 标识字符串中的第一个匹配位置,r,loops,if-statement,substring,R,Loops,If Statement,Substring,我有一个字符串(“00010000”),需要确定我们看到第一个“1”的位置。(这告诉我客户的活跃月份) 我的数据集如下所示: id <- c(1:5) seq <- c("00010000","00001000","01000000","10000000","00010000") df <- data.frame(id,seq) 然而,对于我的数据(包含36个月)来说,这不是一个理想的解决方案 我想将循环与ifelse语句一起使用,但我确实在语法方面遇到了困难 for (i

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

我的数据集如下所示:

id  <- c(1:5)
seq <- c("00010000","00001000","01000000","10000000","00010000")
df <- data.frame(id,seq)
然而,对于我的数据(包含36个月)来说,这不是一个理想的解决方案

我想将循环与ifelse语句一起使用,但我确实在语法方面遇到了困难

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

如果您有任何想法,我们将不胜感激

跳过循环和
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
编辑:只是为了好玩,因为Frank没有将他的评论转换成答案,下面是
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

或者尝试
stringi

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

您可以使用
gregexpr

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

以下内容可以完成此工作:

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

另一个,使用
log

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

使用
sub

nchar(sub('1.*', '', seq))+1
#[1] 4 5 2 1 4
一些比较:

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
库(stringi)
图书馆(stringr)

seq我认为strsplit可能会有所帮助。这个问题是,如果有多个“1”,它将同时报告两个,而不仅仅是第一个。使用
regexpr
只获取第一个。第一个对我来说很有用(聪明的解决方案),但这个也很有意义。精彩的!明显的字符串为“00010000”,但应注意,这可能是双字符,具体取决于编码。在这种情况下,应该首先调用
strtrim
,给出预期的长度,否则
strsplit
可能没有预期的结果。啊,好技巧。我想到了messier
sappy(strsplit(c(“01001”,“10000”),”,fixed=TRUE),函数(x),它(x==“1”)[1])
你应该使用
微基准来计时。它比
系统更可靠。时间
@Thomas所有的基准测试都以秒为单位,在
mocrobenchmark
中没有必要。您可以在
regexpr
中添加“fixed=TRUE”以提高性能。
nchar(sub('1.*', '', seq))+1
#[1] 4 5 2 1 4
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