【问题标题】:Parsing String and splitting it in R解析字符串并将其拆分为 R
【发布时间】:2018-09-20 01:35:04
【问题描述】:

我在处理 R 中的字符串时遇到了某种正则表达式问题。

我有 RNAfold 软件提供的数据结构,如下所示:

"....(((..(((((((((.(.((((((((((((.........)))))))) ))).))))))))..))).."

这是 miRNA 的典型二级结构,但我也有其他不是 miRNA 的序列,看起来有点像这样:

...((((.....))))............(((((((((...)(..(((..( (((...(((((.....)))).))...))).))).))...))))))).. .....

第二个序列有两个发夹环,一个在开头,另一个在中间,而第一个序列只有一个发夹环在中间。

点(“.”)表示未配对的核苷酸,而“(”表示与其对应的核苷酸配对,表示为“)”。

我想拆分这个字符串,以便我可以得到结构中的词干。

我想得到的输出是:

输入:

[1] "....(((..((((((((.(((((((((((.........))))))))))).))))))))..))).."

输出:

[1] "....(((..((((((((.(((((((((((........."
[2] "))))))))))).))))))))..))).."

这样我就可以数出分割的字符串数和词干数了。

第二个序列的结果是:

输入:

[1] ...((((.....))))...........(((((((...((..(((..((((...((((((.....)))).))...)))).))).))...))))))).......

输出:

[1] "...((((....."
[2] "))))...........(((((((...((..(((..((((...((((((....."
[3] ")))).))...)))).))).))...)))))))......."

所以本质上,我想要的是解析字符串,以便在找到“)”符号时将它们拆分,保留字符串的所有符号。

我已经尝试过使用 strplit() 和一些正则表达式变体,但我没能找到诀窍...

有什么帮助吗?

谢谢

【问题讨论】:

  • 如果x 是您的字符串,您可以使用strsplit(x, "\\((?=(\\.+\\)))", perl = TRUE)[[1]],但这会将点保留在新字符串的开头而不是前一个字符串的结尾
  • 啊啊,差异与我想要的无关。非常感谢!!!!
  • 我真的不明白您的预期结果应该是什么,以及在这种情况下您所说的“茎”是什么意思:茎环结构的“茎”通常是 配对的 地区。目前尚不清楚这如何对应于您想要的输出。 — 话虽如此,这是一个众所周知的非常规字符串,这意味着正则表达式是分析它的错误工具。你也许可以用正则表达式破解一些东西,但我真诚的建议是,不要——改用正确的工具:上下文无关语法。

标签: r regex strsplit


【解决方案1】:

您可以执行lookahead 并查找以右括号结尾的点,这些点紧跟在左括号之后。

x <- c("....(((..((((((((.(((((((((((..))))))))))).))))))))..)))..", 
       "...((((.....))))...........(((((((...((..(((..((((...((((((.....)))).))...)))).))).))...))))))).......")
strsplit(x, "\\((?=(\\.+\\)))", perl = TRUE)
# [[1]]
# [1] "....(((..((((((((.(((((((((("  "..))))))))))).))))))))..))).."
# 
# [[2]]
# [1] "...((("  ".....))))...........(((((((...((..(((..((((...((((("
# [3] ".....)))).))...)))).))).))...)))))))......."

【讨论】:

    【解决方案2】:

    如果您想计算字符,这样做可能更方便:

    x <- "...((((.....))))...........(((((((...((..(((..((((...((((((.....)))).))...)))).))).))...)))))))......."
    
    
    with(rle(strsplit(x, "")[[1]]), setNames(lengths, values))
    ##  .  (  .  )  .  (  .  (  .  (  .  (  .  (  .  )  .  )  .  )  .  )  .  )  .  )  . 
    ##  3  4  5  4 11  7  3  2  2  3  2  4  3  6  5  4  1  2  3  4  1  3  1  2  3  7  7 
    

    【讨论】:

      【解决方案3】:

      您可以使用 DavidArenburg 的 逻辑获得您指定的输出,但有所不同 - David 使用 lookahead 正则表达式来查找该模式之前的 ( .{N}) 其中N 可以是任何数字。可变长度的lookbehind(其中模式包含未指定的# of a 字符)是理想的,但不起作用(不允许读取)。诀窍是反转字符串以使用可变长度的前瞻,就像可变长度的后瞻可能操作一样。

      数据

      S <- c("....(((..((((((((.(((((((((((.........))))))))))).))))))))..)))..", "...((((.....))))...........(((((((...((..(((..((((...((((((.....)))).))...)))).))).))...))))))).......")
      

      功能

      reverse_string <- function(S) {
          paste(rev(unlist(strsplit(S, ""))), collapse="")
      }
      
      myfun <- function(S) {
          T <- reverse_string(S)
          result <- unlist(strsplit(T, "\\)(?=(\\.+\\())", perl = TRUE))
          setNames(rev(sapply(result, function(i) reverse_string(i))), NULL)
      }
      

      结果

      lapply(S, myfun)
      
      # [[1]]
      # [1] "....(((..((((((((.(((((((((((........."
      # [2] ")))))))))).))))))))..))).."            
      
      # [[2]]
      # [1] "...((((....."                                       
      # [2] ")))...........(((((((...((..(((..((((...((((((....."
      # [3] "))).))...)))).))).))...)))))))......." 
      

      【讨论】:

        猜你喜欢
        • 2016-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-09
        • 2019-05-14
        • 2021-10-29
        • 1970-01-01
        相关资源
        最近更新 更多