间距矢量按规则模式

owe*_*n88 5 regex r vector pattern-matching

我有一个矢量

vec <- c("ab", "#4", "gw", "#29", "mp", "jq", "#35", "ez")
Run Code Online (Sandbox Code Playgroud)

它通常遵循两个不同字符串序列之间交替的模式(第一个序列全部是字母顺序,第二个序列是数字,符号为#).

但是有些情况下没有出现#term:所以在上面mp和之间jq,然后再次出现ez.我想定义一个用字符串"填补空白"的函数#,这样我就可以输出:

 [1] "ab" "#4" "gw" "#29" "mp" "#" "jq" "#35" "ez" "#"
Run Code Online (Sandbox Code Playgroud)

然后我将转换为数据框

   V1  V2
1  ab  #4
2  gw  #29
3  mp  #
4  jq  #35
5  ez  #
Run Code Online (Sandbox Code Playgroud)

到目前为止,我的尝试相当笨重,依赖于遍历向量并填补空白.我有兴趣看到更优雅的解决方案.


我的解决方案

greplSpace <- function(pattern, replacement, x){

  j <- 1

  while( j < length(x) ){
    if(grepl(pattern, x[j+1]) ){
      j <- j+2 
    } else {
      x <- c( x[1:j], replacement, x[(j+1):length(x)] )
      j <- j+2
    }
  }

  if( ! grepl(pattern, tail(x,1) ) ){ x <- c(x, replacement) }

  return(x)
}

library(magrittr)

vec <- c("ab", "#4", "gw", "#29", "mp", "jq", "#35", "ez")

vec %>% greplSpace("#", "#", . ) %>% 
        matrix(ncol = 2, byrow = TRUE) %>%
        as.data.frame
Run Code Online (Sandbox Code Playgroud)

www*_*www 5

从您的开始vec,我们可以直接使用,一些函数创建您期望的数据框.

library(dplyr)
library(tidyr)
library(stringr)

vec <- c("ab", "#4", "gw", "#29", "mp", "jq", "#35", "ez")

dat <- data_frame(Value = vec)

dat2 <- dat %>%
  mutate(String = !str_detect(vec, "#"),
         Key = ifelse(String, "V1", "V2"),
         Row = cumsum(String)) %>%
  select(-String) %>%
  spread(Key, Value, fill = "#") %>%
  select(-Row)

dat2
# # A tibble: 5 x 2
#   V1    V2   
#   <chr> <chr>
# 1 ab    #4   
# 2 gw    #29  
# 3 mp    #    
# 4 jq    #35  
# 5 ez    #   
Run Code Online (Sandbox Code Playgroud)