Eu tenho um quadro de dados, assim:
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'))
Como você pode ver, algumas entradas na director
coluna são vários nomes separados por vírgulas. Eu gostaria de dividir essas entradas em linhas separadas, mantendo os valores da outra coluna. Por exemplo, a primeira linha no quadro de dados acima deve ser dividida em duas linhas, com um único nome cada na director
coluna e 'A' na AB
coluna.
Respostas:
Esta velha questão freqüentemente está sendo usada como alvo enganoso (marcada com
r-faq
). Até hoje, ele foi respondido três vezes, oferecendo 6 abordagens diferentes, mas carece de uma referência como orientação de qual das abordagens é a mais rápida 1 .As soluções comparadas incluem
data.table
métodos e doisdplyr
/tidyr
abordagens,splitstackshape
Solução de Ananda ,data.table
métodos de Jaap .No geral, 8 métodos diferentes foram avaliados em 6 tamanhos diferentes de quadros de dados usando o
microbenchmark
pacote (veja o código abaixo).Os dados de amostra fornecidos pelo OP consistem apenas em 20 linhas. Para criar quadros de dados maiores, essas 20 linhas são simplesmente repetidas 1, 10, 100, 1000, 10.000 e 100.000 vezes, o que resulta em tamanhos de problema de até 2 milhões de linhas.
Resultados de referência
Os resultados do benchmark mostram que para quadros de dados suficientemente grandes, todos os
data.table
métodos são mais rápidos do que qualquer outro método. Para quadros de dados com mais de cerca de 5000 linhas, odata.table
método 2 de Jaap e a varianteDT3
são os mais rápidos, as magnitudes mais rápidas do que os métodos mais lentos.Notavelmente, os tempos dos dois
tidyverse
métodos e dasplistackshape
solução são tão semelhantes que é difícil distinguir as curvas no gráfico. Eles são os mais lentos dos métodos comparados em todos os tamanhos de quadros de dados.Para quadros de dados menores, a solução R de base de Matt e o
data.table
método 4 parecem ter menos sobrecarga do que os outros métodos.Código
Defina a função para execuções de benchmark de tamanho de problema
n
Execute benchmark para diferentes tamanhos de problemas
Prepare os dados para plotagem
Criar gráfico
Informações da sessão e versões do pacote (trecho)
1 Minha curiosidade foi despertada por este comentário exuberante Brilhante! Ordens de magnitude mais rápidas! a uma
tidyverse
resposta de uma pergunta que foi encerrada como uma duplicata desta pergunta.fonte
data.table
,dplyr
, etc.strsplit
fixed=TRUE
. Como o outro tem e isso terá impacto nos tempos. Desde R 4.0.0 , o padrão, ao criar umdata.frame
, éstringsAsFactors = FALSE
, portanto,as.character
pode ser removido.Várias alternativas:
1) duas maneiras com Tabela de dados:
2) um dplyr / tidyr combinação:
3) com tidyrapenas: Com
tidyr 0.5.0
(e posterior), você também pode usar apenasseparate_rows
:Você pode usar o
convert = TRUE
parâmetro para converter números automaticamente em colunas numéricas.4) com base R:
fonte
data.table(id= "X21", a = "chr1;chr1;chr1", b="123;133;134",c="234;254;268")
tornando-sedata.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]
é o que funcionou para mim.Nomeando seu data.frame original
v
, temos isto:Observe o uso de
rep
para construir a nova coluna AB. Aqui,sapply
retorna o número de nomes em cada uma das linhas originais.fonte
vapply
? Existe algo que o tornavapply
mais apropriado aqui?sapply(s, length)
pode ser substituído porlengths(s)
.Atrasado para a festa, mas outra alternativa generalizada é usar
cSplit
do meu pacote "splitstackshape" que tem umdirection
argumento. Defina como"long"
para obter o resultado que você especificar:fonte
fonte
Outro Benchmark resultante do uso
strsplit
de base pode atualmente ser recomendado para dividir strings separadas por vírgulas em uma coluna em linhas separadas , já que era o mais rápido em uma ampla gama de tamanhos:Observe que o uso
fixed=TRUE
tem um impacto significativo nos tempos.Métodos Comparados:
Bibliotecas:
Dados:
Resultados de computação e tempo:
Observe, métodos como
retornar um
strsplit
paraunique
diretor e pode ser comparável commas, no meu entendimento, isso não foi perguntado.
fonte