Как применить отдельный_rows () ко всем столбцам, передавая параметр `sep`? - PullRequest
0 голосов
/ 06 ноября 2019

Довольно просто: у меня есть фрейм данных, в котором значения во многих столбцах нужно разделить на свои собственные строки, исходя из ; s в качестве разделителя.

После прочтения немного

df %>%
   Reduce(separate_rows_, x = colnames)

работает, за исключением того, что я не могу передать параметр sep (поэтому он также разделяется пробелами, запятыми и другими не алфавитно-цифровымисимволы).

В одном ответе предлагалось написать модифицированную версию функции, включающую параметр, но я не смог заставить ее работать:

Reduce(f = function(y) separate_rows_(sep = ";"), x = colnames)

Что я делаю неправильно?

Сказав это, мое идеальное решение было бы решением проблемы тидиверса, если бы оно было чище (возможно, map_dfr?);но, очевидно, любое решение лучше, чем ничего:).

Вот пример данных:

structure(list(q1 = c("1,2,3,4", "2,4"), q2 = c("a,b", "e,f"), 
q3 = c("c,d", "g,h,z")), row.names = 1:2, class = "data.frame")

Ожидаемый результат:

structure(list(q1 = c("1", "1", "1", "1", "2", "2", "2", "2", 
"3", "3", "3", "3", "4", "4", "4", "4", "2", "2", "2", "2", "2", 
"2", "4", "4", "4", "4", "4", "4"), q2 = c("a", "a", "b", "b", 
"a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "e", 
"e", "e", "f", "f", "f", "e", "e", "e", "f", "f", "f"), q3 = c("c", 
"d", "c", "d", "c", "d", "c", "d", "c", "d", "c", "d", "c", "d", 
"c", "d", "g", "h", "z", "g", "h", "z", "g", "h", "z", "g", "h", 
"z")), row.names = c(NA, -28L), class = "data.frame")

Процесс, который я хочу упростить, ненеобходимо передать имя каждого столбца следующим образом:

output <- test %>% 
  separate_rows(q1, sep = ",") %>% 
  separate_rows(q2, sep = ",") %>% 
  separate_rows(q3, sep = ",")  

1 Ответ

2 голосов
/ 07 ноября 2019

Вы можете использовать purrr::reduce, который применяет данную функцию .f к .init и первый элемент .x, затем применяет функцию к выходу этого и второго элемента .x и т. Д. пока все элементы .x не будут использованы.

В формуле аргумента .f .x - это предыдущий вывод (или .init для первого запуска), а .y - заданный элемент аргумента .x для reduce.

library(tidyverse)

reduce(.init = df, .x = names(df), .f = ~separate_rows(.x, .y, sep = ','))
# equiv to: reduce(.init = df, .x = names(df), .f = separate_rows, sep = ',')

Как отмечает Акрун в комментариях, это также можно сделать в базе R с кодом ниже (тот же вывод)

Reduce(function(x, y) separate_rows(x, y, sep=","), names(df), init = df)

#    q1 q2 q3
# 1   1  a  c
# 2   1  a  d
# 3   1  b  c
# 4   1  b  d
# 5   2  a  c
# 6   2  a  d
# 7   2  b  c
# 8   2  b  d
# 9   3  a  c
# 10  3  a  d
# 11  3  b  c
# 12  3  b  d
# 13  4  a  c
# 14  4  a  d
# 15  4  b  c
# 16  4  b  d
# 17  2  e  g
# 18  2  e  h
# 19  2  e  z
# 20  2  f  g
# 21  2  f  h
# 22  2  f  z
# 23  4  e  g
# 24  4  e  h
# 25  4  e  z
# 26  4  f  g
# 27  4  f  h
# 28  4  f  z
...