Mam ramkę danych, taką jak ta:
data.frame(director = c("Aaron Blaise,Bob Walker", "Akira Kurosawa",
"Alan J. Pakula", "Alan Parker", "Alejandro Amenabar", "Alejandro Gonzalez Inarritu",
"Alejandro Gonzalez Inarritu,Benicio Del Toro", "Alejandro González Iñárritu",
"Alex Proyas", "Alexander Hall", "Alfonso Cuaron", "Alfred Hitchcock",
"Anatole Litvak", "Andrew Adamson,Marilyn Fox", "Andrew Dominik",
"Andrew Stanton", "Andrew Stanton,Lee Unkrich", "Angelina Jolie,John Stevenson",
"Anne Fontaine", "Anthony Harvey"), AB = c('A', 'B', 'A', 'A', 'B', 'B', 'B', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'A'))
Jak widać, niektóre wpisy w director
kolumnie to wiele nazw oddzielonych przecinkami. Chciałbym podzielić te wpisy na osobne wiersze, zachowując wartości z drugiej kolumny. Na przykład, pierwszy wiersz powyższej ramki danych powinien zostać podzielony na dwa wiersze, z których każdy ma jedną nazwę w director
kolumnie i „A” w AB
kolumnie.
Odpowiedzi:
To stare pytanie jest często używane jako cel podwójny (oznaczony
r-faq
). Na dzień dzisiejszy trzykrotnie udzielono odpowiedzi, oferując 6 różnych podejść, ale brakuje w nim punktu odniesienia jako wskazówki, które z podejść jest najszybsze 1 .Wzorcowe rozwiązania obejmują
data.table
metody i dwie metodydplyr
/tidyr
podejścia Jaapa ,splitstackshape
Rozwiązanie Anandy ,data.table
metod Jaapa .Ogólnie 8 różnych metod zostało przetestowanych na 6 różnych rozmiarach ramek danych przy użyciu
microbenchmark
pakietu (patrz kod poniżej).Przykładowe dane podane przez PO składają się tylko z 20 wierszy. Aby utworzyć większe ramki danych, te 20 wierszy jest po prostu powtarzanych 1, 10, 100, 1000, 10000 i 100000 razy, co daje rozmiar problemu do 2 milionów wierszy.
Wyniki testów porównawczych
Wyniki testów porównawczych pokazują, że w przypadku wystarczająco dużych ramek danych wszystkie
data.table
metody są szybsze niż jakakolwiek inna metoda. W przypadku ramek danych zawierających więcej niż około 5000 wierszy,data.table
metoda 2 Jaapa i wariantDT3
są najszybsze, a wielkości są szybsze niż najwolniejsze metody.Co ciekawe, czasy obu
tidyverse
metod isplistackshape
rozwiązania są tak podobne, że trudno jest rozróżnić krzywe na wykresie. Są to najwolniejsze z testowanych metod dla wszystkich rozmiarów ramek danych.W przypadku mniejszych ramek danych podstawowe rozwiązanie Matta R i
data.table
metoda 4 wydają się mieć mniejszy narzut niż inne metody.Kod
Zdefiniuj funkcję dla serii testów porównawczych o rozmiarze problemu
n
Uruchom test porównawczy dla różnych rozmiarów problemów
Przygotuj dane do wykreślenia
Utwórz wykres
Informacje o sesji i wersje pakietów (fragment)
1 Ten żywiołowy komentarz wzbudził moją ciekawość. Świetnie ! Rzędy wielkości szybciej! na odpowiedź na pytanie, które zostało zamknięte jako duplikat tego pytania.
tidyverse
źródło
data.table
,dplyr
itpstrsplit
fixed=TRUE
. Tak jak inni to mają, a to będzie miało wpływ na czasy. Od wersji 4.0.0 wartość domyślna podczas tworzenia plikudata.frame
tostringsAsFactors = FALSE
, więcas.character
mogła zostać usunięta.Kilka alternatyw:
1) na dwa sposoby z Tabela danych:
2) a dplyr / tidyr połączenie:
3) z tidyrtylko: Z
tidyr 0.5.0
(i później), można też po prostu użyćseparate_rows
:Możesz użyć tego
convert = TRUE
parametru, aby automatycznie przekształcić liczby w kolumny liczbowe.4) z podstawą R:
źródło
data.table(id= "X21", a = "chr1;chr1;chr1", b="123;133;134",c="234;254;268")
stawanie siędata.table(id = c("X21","X21",X21"), a=c("chr1","chr1","chr1"), b=c("123","133","134"), c=c("234","254","268"))
?setDT(dt)[,lapply(.SD, function(x) unlist(tstrsplit(x, ";",fixed=TRUE))), by = ID]
to działa dla mnie.Nazywając swój oryginalny data.frame
v
, mamy to:Zwróć uwagę na użycie
rep
do zbudowania nowej kolumny AB. Tutajsapply
zwraca liczbę nazw w każdym z oryginalnych wierszy.źródło
vapply
? Czy jest coś, co jestvapply
bardziej odpowiednie?sapply(s, length)
można by go zastąpićlengths(s)
.Spóźniłem się na imprezę, ale inną uogólnioną alternatywą jest użycie
cSplit
mojego pakietu "splitstackshape", który madirection
argument. Ustaw to, aby"long"
uzyskać określony wynik:źródło
źródło
Można obecnie zalecić inny test porównawczy wynikający
strsplit
z bazy, aby podzielić ciągi oddzielone przecinkami w kolumnie na oddzielne wiersze , ponieważ był najszybszy w szerokim zakresie rozmiarów:Pamiętaj, że używanie
fixed=TRUE
ma znaczący wpływ na czasy.Porównywane metody:
Biblioteki:
Dane:
Wyniki obliczeń i czasu:
Uwaga, metody takie jak
zwraca
strsplit
dlaunique
dyrektora i może być porównywalny zale według mojego rozumienia nie było to wymagane.
źródło