Разбить значения фрейма и поместить в группу в R? - PullRequest
2 голосов
/ 11 июля 2019

Учитывая столбец данных, например:

df <- structure(list(ingredients = structure(c("en:xylitol", "en:water,en:sugar,en:glucose-fructose-syrup,en:fructose,en:glucose,fr:dioxyde-de-carbone,en:acid,en:citric-acid,en:natural-flavouring,en:flavouring,fr:arome-quinine,fr:quinine", 
"en:sugar,en:corn-syrup,fr:sirop-de-mais-a-teneur-elevee-en-fructose,en:citric-acid,en:natural-and-artificial-flavouring,en:artificial-flavouring,en:natural-flavouring,en:flavouring,en:colour,fr:rouge-40,fr:bleu-1", 
"pt:semoule-de-ble-dur,pt:pesto,pt:basilic,pt:fromage-en-poudre,pt:ail-et-epinars,pt:basilic-contient-du-gluten-et-des-derives-de-lait", 
"pt:pimenta-branca", "en:water,es:pasta-de-almendras-tostadas,en:sugar", 
"en:water,es:zumo-de-chufas,en:sugar,en:dextrose,en:glucose,es:estabilizantes,es:412,es:carragenanos,es:e-407,es:carboximetil-celulosa,es:e-466,es:monodigliceridos-de-acidos-grasos,en:mono-and-diglycerides-of-fatty-acids,en:emulsifier,en:flavouring,en:guar-gum,es:e", 
"es:aceitunas-cacerena,en:water,en:salt,en:stabiliser,es:579,es:categoria,es:i,es:calibre,es:gluconato-ferroso,es:e,es:240,es:260", 
"en:carbonated-water,en:water,en:sugar,en:colour,fr:caramel-e150d,en:natural-flavouring,en:flavouring,en:acid,en:phosphoric-acid,fr:extrait-de-genepi,fr:cafeine", 
"en:pear,en:fruit,es:variedad,es:70-mm,es:conferencia,es:categoria-i,es:calibre,es:65"
), .Dim = c(10L, 1L))), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame"))

Я хочу разделить каждую строку разделителем "," и поместить выделенный вывод в группу.

Например:

en:water,es:pasta-de-almendras-tostadas,en:sugar 

превратится в

group ingredient
1     en:water
1     es:pasta-de-almendras-tostadas
1     en:sugar

Следующим шагом будет удаление префикса XX:

Посоветуйте, пожалуйста, как это сделать?

Ответы [ 5 ]

3 голосов
/ 11 июля 2019

Мы можем использовать separate_rows из tidyr после добавления столбца последовательности

library(tidyr)
library(dplyr)
df %>% 
    mutate(group = row_number()) %>%
    separate_rows(ingredients, sep=",")
2 голосов
/ 11 июля 2019

Мы можем использовать data.table:

require(data.table)
setDT(df)[, lapply(.SD, function(x){
                        unlist(tstrsplit(x, ",", fixed=TRUE))}), 
          by = seq.int(nrow(df))]

или просто использовать base:

stack(setNames(strsplit(df$ingredients,','), seq.int(nrow(df))))

или использовать splitstackshape пакет:

require(splitstackshape)

cSplit(cbind(seq.int(nrow(df)), df), "ingredients", ",", "long")

#>    seq.int(nrow(df))               ingredients
#> 1:                 1                en:xylitol
#> 2:                 2                  en:water
#> 3:                 2                  en:sugar
#> 4:                 2 en:glucose-fructose-syrup
#> 5:                 2               en:fructose
#> 6:                 2                en:glucose
#...# … with 76 more rows (manually trimmed the output)
2 голосов
/ 11 июля 2019

Вот ответ, включая удаление префикса:

library(tidyverse)

df %>% 
    mutate(ingredients = str_split(ingredients, ","),
           row_num = row_number()) %>% 
    unnest() %>% 
    mutate(ingredients = str_remove(ingredients, "^[^:]+(:)"))

#> # A tibble: 82 x 2
#>    row_num ingredients           
#>      <int> <chr>                 
#>  1       1 xylitol               
#>  2       2 water                 
#>  3       2 sugar                 
#>  4       2 glucose-fructose-syrup
#>  5       2 fructose              
#>  6       2 glucose               
#>  7       2 dioxyde-de-carbone    
#>  8       2 acid                  
#>  9       2 citric-acid           
#> 10       2 natural-flavouring    
#> # … with 72 more rows
2 голосов
/ 11 июля 2019

Вы можете использовать strsplit и добавить столбец группы в соответствии с номером списка, наконец rbind вещь.

l <- strsplit(df$ingredients, ",")

res <- data.frame(do.call(rbind, sapply(seq(l), function(x) 
  cbind(group=x, ingredient=l[[x]]))))
head(res)
#   group                ingredient
# 1     1                en:xylitol
# 2     2                  en:water
# 3     2                  en:sugar
# 4     2 en:glucose-fructose-syrup
# 5     2               en:fructose
# 6     2                en:glucose
1 голос
/ 11 июля 2019

Используя предложение @ akrun для функции separa_rows, я только что использовал следующий код с регулярным выражением ^[a-z]{2}:, что означает, что я хочу отфильтровать в начале каждого значения первые 2 символа a-z и столбец (:).

df %>% 
  dplyr::mutate(group = row_number()) %>% 
  tidyr::separate_rows(ingredients, sep = ",", convert = TRUE) %>%
  dplyr::mutate(ingredients = str_remove(ingredients, pattern = "^[a-z]{2}:")) %>%
  dplyr::distinct(ingredients, .keep_all = TRUE)
...