I have a data frame, like so:
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'))
As you can see, some entries in the director
column are multiple names separated by commas. I would like to split these entries up into separate rows while maintaining the values of the other column. As an example, the first row in the data frame above should be split into two rows, with a single name each in the director
column and 'A' in the AB
column.
This old question frequently is being used as dupe target (tagged with
r-faq
). As of today, it has been answered three times offering 6 different approaches but is lacking a benchmark as guidance which of the approaches is the fastest1.The benchmarked solutions include
data.table
methods and twodplyr
/tidyr
approaches,splitstackshape
solution,data.table
methods.Overall 8 different methods were benchmarked on 6 different sizes of data frames using the
microbenchmark
package (see code below).The sample data given by the OP consists only of 20 rows. To create larger data frames, these 20 rows are simply repeated 1, 10, 100, 1000, 10000, and 100000 times which give problem sizes of up to 2 million rows.
Benchmark results
The benchmark results show that for sufficiently large data frames all
data.table
methods are faster than any other method. For data frames with more than about 5000 rows, Jaap'sdata.table
method 2 and the variantDT3
are the fastest, magnitudes faster than the slowest methods.Remarkably, the timings of the two
tidyverse
methods and thesplistackshape
solution are so similar that it's difficult to distiguish the curves in the chart. They are the slowest of the benchmarked methods across all data frame sizes.For smaller data frames, Matt's base R solution and
data.table
method 4 seem to have less overhead than the other methods.Code
Define function for benchmark runs of problem size
n
Run benchmark for different problem sizes
Prepare data for plotting
Create chart
Session info & package versions (excerpt)
1My curiosity was piqued by this exuberant comment Brilliant! Orders of magnitude faster! to a
tidyverse
answer of a question which was closed as a duplicate of this question.Naming your original data.frame
v
, we have this:Note the use of
rep
to build the new AB column. Here,sapply
returns the number of names in each of the original rows.Late to the party, but another generalized alternative is to use
cSplit
from my "splitstackshape" package that has adirection
argument. Set this to"long"
to get the result you specify:Several alternatives:
1) two ways with
data.table
:2) a
dplyr
/tidyr
combination: Alternatively, you can also use thedplyr
/tidyr
combination:3) with
tidyr
only: Withtidyr 0.5.0
(and later), you can also just useseparate_rows
:You can use the
convert = TRUE
parameter to automatically convert numbers into numeric columns.4) with base R: