Извлечение значений из длинной строки и создание новых столбцов на основе количества скобок в r - PullRequest
0 голосов
/ 22 февраля 2020

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>

Исходный набор данных содержит более 10000 строк, а количество скобок в столбце ab c может быть больше или меньше 3.

Ответы [ 2 ]

1 голос
/ 22 февраля 2020

Вот моя попытка. Я использовал регулярное выражение для извлечения алфавитов и чисел, оставшихся в скобках. 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")) 
1 голос
/ 22 февраля 2020

Вот базовое решение R

dfout <- cbind(df,
               gsub("\\(|\\)",
                    "",
                    do.call(rbind,
                            lapply(z <- with(df,regmatches(abc,gregexpr("\\(\\w+\\)",abc))),
                                   `length<-`,
                                   max(lengths(z))))))

такое, что

> dfout
  index                                          abc      1        2      3
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>
...