2015-10-22 8 views
11

Mam zestaw danych, który składa się z komunikacji e-mail. Przykład:Jak korzystać z tidyr :: oddzielne, gdy liczba potrzebnych zmiennych jest nieznana

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]")) 

W powyższym przykładzie jest to na tyle proste, aby zobaczyć, jak wiele zmiennych muszę, więc może po prostu wykonaj następujące czynności:

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 

Jednak mój zestaw danych jest długa 4000 rekordy i ja raczej nie przechodź i znajdź wiersz z największą liczbą elementów, aby móc określić, ile zmiennych muszę utworzyć. Moje podejście do obsługi to jest najpierw podzielić kolumnę siebie i uzyskać długość każdego rozłamu, a następnie znaleźć max:

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

Ale to wydaje się nieefektywne. Czy jest lepszy sposób na zrobienie tego?

+0

Może również ' biblioteka (data.table); cbind (dat, setDT (dat) [, tstrsplit (to, ",")]) ' –

+0

Wydaje się rozsądnym rozwiązaniem zamiast ładowania innej paczki. jeśli już ładujesz 'tidyverse' możesz użyć' map_dbl' i usunąć 'unlist', aby uczynić go nieco czystszym. 'dat $ to%>% str_split (", ")%>% map_dbl (~ length (.))%>% max()' – Tunn

Odpowiedz

6

Mogliśmy użyć cSplit

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

To jest dobre pytanie - mój zwykły repsonse jest użycie strsplit, potem unnest i spread, co również nie jest bardzo wydajny:

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 
+0

Myślę, że to jest lepsze, ponieważ możesz opcjonalnie nie rozprzestrzeniać się na końcu. Dzielenie e-maili na te osobne kolumny wydaje się głupie. – bramtayl

+0

@bramtayl Mam wrażenie, że osobno celowo to utrudnia, więc nie kończysz na szerokich danych, a nie długo – jeremycg

+0

@bramtayl Zgadzam się, że posiadanie szerokich danych w tym scenariuszu nie ma sensu (i nie ma sensu większość sytuacji), ale był to łatwy pomysł, aby otoczyć głowę, aby uzyskać podstawowy problem używania "oddzielnego", gdy nie wiesz, ile nowych kolumn będziesz potrzebować. Rozwiązanie firmy Akrun jest nadal dobre, ponieważ ustawiasz 'direction =" long "', aby uzyskać wszystkie wiadomości e-mail w jednej kolumnie. – brittenb

Powiązane problemy