Как использовать tidyr:: separate, когда количество необходимых переменных неизвестно

У меня есть набор данных, который состоит из сообщения электронной почты. Пример:

library(dplyr)
library(tidyr)

dat <- data_frame('date' = Sys.time(), 
                  'from' = c("[email protected]", "[email protected]", 
                             "[email protected]", "[email protected]"), 
                  'to' = c("[email protected],[email protected]", "[email protected]", 
                           "[email protected],[email protected],[email protected]", "[email protected]"))

В приведенном выше примере достаточно просто посмотреть, сколько переменных мне нужно, поэтому я мог бы просто сделать следующее:

dat %>% separate(to, into = paste0("to_", 1:3), sep = ",", extra = "merge", fill = "right")

#Source: local data frame [4 x 5]
#
#                 date                from                to_1                to_2              to_3
#               (time)               (chr)               (chr)               (chr)             (chr)
#1 2015-10-22 14:52:41   [email protected]   [email protected] [email protected]                NA
#2 2015-10-22 14:52:41   [email protected] [email protected]                  NA                NA
#3 2015-10-22 14:52:41 [email protected]     [email protected]   [email protected] [email protected]
#4 2015-10-22 14:52:41     [email protected]   [email protected]                  NA                NA

Однако мой набор данных составляет 4000 записей, и я бы предпочел не проходить и найти строку с большим количеством элементов в ней, чтобы я мог определить, сколько переменных мне нужно создать. Мой подход к обработке заключается в том, чтобы сначала разбить столбец и получить длину каждого раскола, а затем найти max:

n_vars <- dat$to %>% str_split(",") %>% lapply(function(z) length(z)) %>% unlist() %>% max()

Но это кажется неэффективным. Есть ли лучший способ сделать это?

Ответ 1

Мы могли бы использовать cSplit

library(splitstackshape) 
cSplit(dat, 'to', ',')

Ответ 2

Это хороший вопрос - мой обычный ответ заключается в использовании strsplit, затем unnest и spread, который также не является суперэффективным:

library(dplyr)
library(tidyr)

dat %>% mutate(to = strsplit(to, ",")) %>%
        unnest(to) %>%
        group_by(from) %>%
        mutate(row = row_number()) %>%
        spread(row, to)

Source: local data frame [4 x 5]

                 date                from                   1                   2                 3
               (time)               (chr)               (chr)               (chr)             (chr)
1 2015-10-22 15:03:17   [email protected]   [email protected] [email protected]                NA
2 2015-10-22 15:03:17   [email protected] [email protected]                  NA                NA
3 2015-10-22 15:03:17 [email protected]     [email protected]   [email protected] [email protected]
4 2015-10-22 15:03:17     [email protected]   [email protected]                  NA                NA