首页 > 解决方案 > 从长字符串中提取值并根据 r 中的括号数创建新列

问题描述

substr()可能是用条件提取值的好方法(在我们的例子中,条件是从括号中提取值),但是有没有方便的方法来提取多个值并创建多个列(新列号与提取值)。

这是一个示例数据:

        index  abc
  1     1      qwer(urt123) qweqwe
  2     2      rte(ret390) qweqwe(tertr213) ityorty(ret435)
  3     3      <NA>
  4     4      ogi(wqe685) qwe(ieow123)
  5     5      cvb(bnm567)

用于创建问题数据框的代码:

data.frame(index = c(1:5),
           abc = c("qwer(urt123) qweqwe", "rte(ret390) qweqwe(tertr213) ityorty(ret435)",
                    NA, "ogi(wqe685) qwe(ieow123)", "cvb(bnm567)"))

最终结果:

        index  abc                                          abc1     abc2     abc3
  1     1      qwer(urt123) qweqwe                          urt123   <NA>     <NA>
  2     2      rte(ret390) qweqwe(tertr213) ityorty(ret435) ret390   tertr213 ret435
  3     3      <NA>                                         <NA>     <NA>     <NA>
  4     4      ogi(wqe685) qwe(ieow123)                     wqe685   ieow123  <NA>
  5     5      cvb(bnm567)                                  bnm567   <NA>     <NA>

原始数据集有 10,000 多行,abc 列中的括号数可能多于或少于 3 个。

标签: rsubstringsubstr

解决方案


这是我的尝试。我使用正则表达式来提取括号内的字母和数字。stri_extract_all_regex()返回一个列表。所以我过去常常unnest_wider()创建新列。最后一步是修改三个列名。使用后unnest_wider()我们得到...1一个列名,例如。包含的任何列名...都已修改;我替换...foo.

library(tidyverse)
library(stringi)

mutate(mydf,
       foo = stri_extract_all_regex(str = abc, pattern = "(?<=\\()[[:alnum:]]+(?=\\))")) %>% 
unnest_wider(foo) %>% 
rename_at(vars(contains("...")),
          .funs = list(~sub(x = ., pattern = "\\.+", replacement = "foo")))

  index abc                                          foo1   foo2     foo3  
  <int> <chr>                                        <chr>  <chr>    <chr> 
1     1 qwer(urt123) qweqwe                          urt123 NA       NA    
2     2 rte(ret390) qweqwe(tertr213) ityorty(ret435) ret390 tertr213 ret435
3     3 NA                                           NA     NA       NA    
4     4 ogi(wqe685) qwe(ieow123)                     wqe685 ieow123  NA    
5     5 cvb(bnm567)                                  bnm567 NA       NA   

数据

mydf <- structure(list(index = 1:5, abc = c("qwer(urt123) qweqwe", "rte(ret390) 
qweqwe(tertr213) ityorty(ret435)", 
NA, "ogi(wqe685) qwe(ieow123)", "cvb(bnm567)")), row.names = c(NA, 
-5L), class = c("tbl_df", "tbl", "data.frame")) 

推荐阅读