отдельный (или похожая функция) с несколькими или без вхождений символа разделения - PullRequest
3 голосов
/ 09 октября 2019

У меня есть такой тиббл

library("tidyverse")
tib <- tibble(x = c("lemon", "yellow, banana", "red, big, apple"))

Я хотел бы создать два новых столбца с именами description и fruit и извлечь последнее слово после запятой , используя separate (если есть запятая; в противном случае я хотел бы просто скопировать слово в ячейку).

Пока у меня есть

tib %>%
    separate(x, ", ", into = c("description", "fruit"), remove = FALSE)

, но это не совсемделай, что я хочу, получая:

# A tibble: 3 x 3
  x               description fruit 
  <chr>           <chr>       <chr> 
1 lemon           lemon       NA    
2 yellow, banana  yellow      banana
3 red, big, apple red         big   
Warning messages:
1: Expected 2 pieces. Additional pieces discarded in 1 rows [3]. 
2: Expected 2 pieces. Missing pieces filled with `NA` in 1 rows [1]. 

Вывод, который я хочу получить:

  x               description fruit 
1 lemon           NA          lemon    
2 yellow, banana  yellow      banana
3 red, big, apple red, big    apple 

Может ли кто-нибудь указать мне на ту часть, которую я пропускаю?

РЕДАКТИРОВАТЬ

Цель не должна быть достигнута с помощью separate. mutate также будет работать, и решения одинаково приветствуются!

Ответы [ 3 ]

2 голосов
/ 09 октября 2019

Может быть лучше с extract. Здесь мы можем использовать группы захвата, чтобы захватить персонажей как группу. Лучше начинать с конца ($) и идти назад, т. Е. Слово (\\w+) в конце перехвачено, следует , или пробел (\\s) и все другие символы в первой группе захвата((.*?))

library(tidyr)
library(dplyr)
tib %>%
   extract(x, into = c("description", "fruit"), remove = FALSE, '(.*?),?\\s?(\\w+$)')

Или с использованием регулярного выражения с separate, указав разделитель в виде ,, за которым следует пробел или начало (^) строки, за которой следует символслово (\\w+) в конце ($) строки

tib %>%
   separate(x, into = c("description", 'fruit'),
       remove = FALSE, '(, |^)(?=\\w+$)') %>%
   mutate(description = na_if(description, ""))

Кроме того, другой вариант с separate будет заключаться в добавлении нового разделителя перед последним словом, а затемиспользуйте это как sep

library(stringr)
tib %>% 
  mutate(x1 = str_replace(x, ',? ?(\\w+)$', ";\\1")) %>% 
  separate(x1, into = c("description", "fruit"), sep=";") %>%
  mutate(description = na_if(description, ""))
# A tibble: 3 x 3
#  x               description fruit 
#  <chr>           <chr>       <chr> 
#1 lemon           <NA>        lemon 
#2 yellow, banana  yellow      banana
#3 red, big, apple red, big    apple 
1 голос
/ 09 октября 2019

Решения на основе регулярных выражений, как и другие два здесь, вероятно, лучше. Но если по какой-либо причине вы хотите вместо этого работать со списками слов, вот еще один вариант.

Разделить текст на список строк. В описании есть все, кроме предмета в позиции length(words). Фрукт - последний пункт. Если с пустой строкой вместо NA все в порядке, вы можете удалить бит na_if.

library(dplyr)

tib <- tibble(x = c("lemon", "yellow, banana", "red, big, apple"))
tib %>%
  mutate(words = strsplit(x, ", "),
         description = purrr::map_chr(words, ~paste(.[-length(.)], collapse = ", ")) %>% na_if(""),
         fruit = purrr::map_chr(words, last))
#> # A tibble: 3 x 4
#>   x               words     description fruit 
#>   <chr>           <list>    <chr>       <chr> 
#> 1 lemon           <chr [1]> <NA>        lemon 
#> 2 yellow, banana  <chr [2]> yellow      banana
#> 3 red, big, apple <chr [3]> red, big    apple

Очевидно, что вы можете затем удалить столбец words - я оставил его, чтобы показать еготипа.

1 голос
/ 09 октября 2019

Вы можете использовать регулярное выражение, чтобы получить описание - заменить последнюю запятую и все, что после нее. ",[^,]+$" соответствует запятой, за которой следует все, что не является запятой до конца.

Для получения фруктов используйте функцию word пакета stringr, чтобы получить последнее слово.

tib %>%
    mutate(desc = if_else(grepl(",", x), sub(",[^,]+$", "", x), NA_character_),
           fruit = stringr::word(x, -1))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...