Estou trabalhando em R e preferiria uma solução dplyr, se possível.
dados de amostra:
data.frame(
col1 = c("a", "b", "c", "d"),
col2 = c("a", "b", "d", "a"),
col3 = rep("a", 4L),
col4 = c("a", "b", "d", "a"),
col5 = c("a", "a", "c", "d"),
col6 = rep(c("b", "a"), each = 2L)
)
col1 | col2 | col3 | col4 | col5 | col6 |
---|---|---|---|---|---|
a | a | a | a | a | b |
b | b | a | b | a | b |
c | d | a | d | c | a |
d | a | a | a | d | a |
Pergunta
Gostaria de saber para cada linha se col1, col2 e col3 são iguais a col4, col5 e col6, mas a ordem de col1 - col3 e col4 - col6 deve ser ignorada.
Portanto, para a linha 1, se col1 - col3 contivesse a,a,b respectivamente, e col4 - col6 contivesse b,a,a respectivamente, isso seria considerado uma correspondência.
Resultado desejado
Coloquei uma nota na coluna "avaliação" para ajudar na compreensão
col1 | col2 | col3 | col4 | col5 | col6 | avaliação |
---|---|---|---|---|---|---|
a | a | a | a | a | b | FALSO (porque 1-3 não é igual a 4-6) |
b | b | a | b | a | b | VERDADEIRO (porque 1-3 é igual a 4-6, se ignorar a ordem) |
c | d | a | d | c | a | VERDADEIRO (porque 1-3 é igual a 4-6, se ignorar a ordem) |
d | a | a | a | d | a | VERDADEIRO (porque 1-3 é igual a 4-6, se ignorar a ordem) |
BaseR:
Dados reproduzíveis:
PS: Por que table() e indentical em vez de sort(), ==, all()? Eu esperaria que fosse melhor dimensionado com o número de colunas (dado o baixo número de valores exclusivos). Exemplo:
PS 2: Substituir
table(x)
porcollapse::fcount(x, sort = TRUE)
dá uma grande aceleração.Usando dplyr você pode fazer o seguinte:
Evite iterar nas linhas
Geralmente, a iteração nas linhas é lenta e descobri que
dplyr::rowwise()
as abordagens se tornam muito lentas com mais de alguns milhares de linhas. Tende a ser mais rápido de usarpurrr::pmap()
e muito mais rápido de iterar nas colunas.abordagem base R
Você poderia pegar a transposição das colunas relevantes e iterar sobre as colunas disso.
tidyverse
abordagem: converter de largo para longoAlternativamente, se você quiser permanecer no
tidyverse
você pode converter de largo para longo:Isso é mais detalhado, mas suspeito que será consideravelmente mais rápido com qualquer conjunto de dados de tamanho razoável.
Na base R você poderia usar
vapply
esort
:Saída:
Como foi observado, você deve evitar operações em linha. Aqui está uma alternativa que compara conjuntos usando uma função auxiliar que classifica com eficiência por linha para que as comparações sejam completamente vetorizadas.
Uma
dplyr
opçãovecsets
poderia ser:A mesma ideia com
purrr::pmap()
:Esta é uma solução excessivamente ineficiente, mas por curiosidade:
A mesma ideia com
purrr:pmap()
:Usando a lógica de transposição do @SamR com
vecsets
:A mesma abordagem usando
data.table::transpose()
:Experimente o código abaixo com
split.default
+colMeans
que deveria dar
Este é bastante detalhado, mas não consigo resistir. Aqui está um com pivotamento: