【问题标题】:split string without loss of characters拆分字符串而不丢失字符
【发布时间】:2013-07-12 20:05:04
【问题描述】:

我希望在某个字符处拆分字符串,同时将该字符保留在第二个结果字符串中。我几乎可以实现所有想要的操作,除了我丢失了我在strsplit 中指定的字符,我猜这被称为分隔符。

有没有办法要求strsplit 保留分隔符?或者我必须使用某种正则表达式吗?谢谢你的任何建议。这似乎是一个非常基本的问题。对不起,如果它是重复的。我更喜欢使用base R。

这是一个展示我目前所拥有的示例:

my.table <- read.table(text = '
                                                            model npar     AICc 
 AA(~region+state+county+city)BB(~region+state+county+city)CC(~1)   17 11111.11
         AA(~region+state+county)BB(~region+state+county)CC(~123)   14 22222.22
                        AA(~region+state)BB(~region+state)CC(~33)   13 33333.33
                                  AA(~region)BB(~region)CC(~4321)    6 44444.44
', header = TRUE, stringsAsFactors = FALSE)

desired.result <- read.table(text = '
                                                      model        CC npar     AICc
 AA(~region+state+county+city)BB(~region+state+county+city)    CC(~1)   17 11111.11
           AA(~region+state+county)BB(~region+state+county)  CC(~123)   14 22222.22
                         AA(~region+state)BB(~region+state)   CC(~33)   13 33333.33
                                     AA(~region)BB(~region) CC(~4321)    6 44444.44
', header = TRUE, stringsAsFactors = FALSE)

split.model  <- strsplit(my.table$model, 'CC\\(')

split.models <- matrix(unlist(split.model), ncol=2, byrow=TRUE, dimnames = list(NULL, c("model", "CC")))

desires.result2 <- data.frame(split.models, my.table[,2:ncol(my.table)])
desires.result2

#                                                       model     CC npar     AICc
# 1 AA(~region+state+county+city)BB(~region+state+county+city)    ~1)   17 11111.11
# 2           AA(~region+state+county)BB(~region+state+county)  ~123)   14 22222.22
# 3                         AA(~region+state)BB(~region+state)   ~33)   13 33333.33
# 4                                     AA(~region)BB(~region) ~4321)    6 44444.44

【问题讨论】:

    标签: regex r split strsplit


    【解决方案1】:

    基本思想是使用从正则表达式到strsplitlook-around操作来得到你想要的结果。但是,它比 strsplit 和积极的前瞻要复杂一些。阅读@JoshO'Brien 的this excellent post 以获得解释。

    pattern <- "(?<=\\))(?=CC)"
    strsplit(my.table$model, pattern, perl=TRUE)
    # [[1]]
    # [1] "AA(~region+state+county+city)BB(~region+state+county+city)"
    # [2] "CC(~1)"                                                    
    
    # [[2]]
    # [1] "AA(~region+state+county)BB(~region+state+county)"
    # [2] "CC(~123)"                                        
    
    # [[3]]
    # [1] "AA(~region+state)BB(~region+state)" "CC(~33)"                           
    
    # [[4]]
    # [1] "AA(~region)BB(~region)" "CC(~4321)"             
    

    当然,我把do.call(rbind, ...)cbind的任务留给你,把最后的desired.output交给你。

    【讨论】:

      【解决方案2】:

      几乎在我发布之后,我就想到使用gsub 插入一个空格,然后在该空格上拆分。不过,我更喜欢 Arun 的回答。

      my.table <- read.table(text = '
                                                                  model npar     AICc 
       AA(~region+state+county+city)BB(~region+state+county+city)CC(~1)   17 11111.11
               AA(~region+state+county)BB(~region+state+county)CC(~123)   14 22222.22
                              AA(~region+state)BB(~region+state)CC(~33)   13 33333.33
                                        AA(~region)BB(~region)CC(~4321)    6 44444.44
      ', header = TRUE, stringsAsFactors = FALSE)
      
      my.table$model <- gsub("CC", " CC", my.table$model)
      
      split.model <- strsplit(my.table$model, ' ')
      
      split.models <- matrix(unlist(split.model), ncol=2, byrow=TRUE, dimnames = list(NULL, c("model", "CC")))
      
      desires.result <- data.frame(split.models, my.table[,2:ncol(my.table)])
      desires.result
      
      #                                                        model        CC npar     AICc
      # 1 AA(~region+state+county+city)BB(~region+state+county+city)    CC(~1)   17 11111.11
      # 2           AA(~region+state+county)BB(~region+state+county)  CC(~123)   14 22222.22
      # 3                         AA(~region+state)BB(~region+state)   CC(~33)   13 33333.33
      # 4                                     AA(~region)BB(~region) CC(~4321)    6 44444.44
      

      【讨论】:

      • 如果你要sub,那么只需执行sub('.*(CC.*)', '\\1', model)sub('CC.*', '', model) 即可获得这两部分(假设你有两部分)
      【解决方案3】:

      ...为什么不把分隔符重新贴上呢?似乎可以省去很多摆弄正则表达式的麻烦。

      split.model <- lapply(strsplit(my.table$model, 'CC\\('), function(x) {
          x[2] <- paste0("CC(", x[2])
          x
      })
      

      【讨论】:

      • 是的但是:1)这种方法的局限性来(不是针对这个问题,而是一般来说)当人们想要搜索例如CA,CB,CC,CD和CE并拆分字符串,如果 CF、CG、... 不要。 2) 您实际上是在遍历所有行并再次粘贴,这可能在较大数据上效率不高(尚未进行基准测试)。
      • @arun 这是对提出的具体问题的回答:如何在不删除特定字符串的情况下搜索它。除非您要处理大量愚蠢的案例(数百万?),否则所有提出的解决方案基本上都是即时的。此外,俗话说,你有执行时间,你有写作时间。提出适当的正则表达式所花费的时间可能会超过运行它所花费的时间。
      • 实际上,在 40k 行的 data.frame 上,这个解决方案需要 0.8 秒,而 regexp 解决方案需要 0.065 秒。现在,我们可以争论 0.8 秒在编码意义上是否是很多时间。我想我已经提到限制是在“一般”情况下。然而,我在 SO(至少在 R-tag 下)观察到的趋势是尽可能提供 generalefficient 解决方案。实际上,编写我的解决方案需要 72 个字符,而你的肯定会更多。所以你真的的意思是思考时间。我想我对此有不同的看法。
      猜你喜欢
      • 1970-01-01
      • 2021-07-06
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-13
      • 1970-01-01
      相关资源
      最近更新 更多