Combinação única de todos os elementos de dois (ou mais) vetores

94

Estou tentando criar uma combinação única de todos os elementos de dois vetores de tamanhos diferentes em R.

Por exemplo, o primeiro vetor é

a <- c("ABC", "DEF", "GHI")

e o segundo são as datas armazenadas como strings atualmente

b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

Eu preciso criar um quadro de dados com duas colunas como esta

> data
    a          b
1  ABC 2012-05-01
2  ABC 2012-05-02
3  ABC 2012-05-03
4  ABC 2012-05-04
5  ABC 2012-05-05
6  DEF 2012-05-01
7  DEF 2012-05-02
8  DEF 2012-05-03
9  DEF 2012-05-04
10 DEF 2012-05-05
11 GHI 2012-05-01
12 GHI 2012-05-02
13 GHI 2012-05-03
14 GHI 2012-05-04
15 GHI 2012-05-05

Então, basicamente, estou procurando uma combinação única considerando todos os elementos de um vetor (a) justapostos com todos os elementos do segundo vetor (b).

Uma solução ideal seria generalizar para mais vetores de entrada.


Veja também:
Como gerar uma matriz de combinações

Gõdel
fonte

Respostas:

138

isso talvez seja o que você está procurando

> expand.grid(a,b)
   Var1       Var2
1   ABC 2012-05-01
2   DEF 2012-05-01
3   GHI 2012-05-01
4   ABC 2012-05-02
5   DEF 2012-05-02
6   GHI 2012-05-02
7   ABC 2012-05-03
8   DEF 2012-05-03
9   GHI 2012-05-03
10  ABC 2012-05-04
11  DEF 2012-05-04
12  GHI 2012-05-04
13  ABC 2012-05-05
14  DEF 2012-05-05
15  GHI 2012-05-05

Se a ordem resultante não for a que você deseja, você pode classificar depois. Se você nomear os argumentos como expand.grid, eles se tornarão nomes de colunas:

df = expand.grid(a = a, b = b)
df[order(df$a), ]

E expand.gridgeneraliza para qualquer número de colunas de entrada.

shhhhimhuntingrabbits
fonte
4
E sem precisar plyrapenas fazer uma espécie:result <- expand.grid(a=a,b=b); result <- result[order(result$a,result$b),];
thelatemail
Alguém com mais reputação do que eu é capaz de aceitar essa resposta?
Josh
Se a ordem e os nomes devem ser como na pergunta:expand.grid(b=b,a=a)[2:1]
GKi
Observe que o título é Combinações únicas - esta resposta resolve o problema de OP, mas se as 2 colunas forem do mesmo tipo de dados e você aplicar expand.grid, você terá permutações exclusivas, não combinações exclusivas
Brent
27

O tidyrpacote oferece uma boa alternativa crossing, que funciona melhor do que a expand.gridfunção clássica porque (1) as strings não são convertidas em fatores e (2) a classificação é mais intuitiva:

library(tidyr)

a <- c("ABC", "DEF", "GHI")
b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

crossing(a, b)

# A tibble: 15 x 2
       a          b
   <chr>      <chr>
 1   ABC 2012-05-01
 2   ABC 2012-05-02
 3   ABC 2012-05-03
 4   ABC 2012-05-04
 5   ABC 2012-05-05
 6   DEF 2012-05-01
 7   DEF 2012-05-02
 8   DEF 2012-05-03
 9   DEF 2012-05-04
10   DEF 2012-05-05
11   GHI 2012-05-01
12   GHI 2012-05-02
13   GHI 2012-05-03
14   GHI 2012-05-04
15   GHI 2012-05-05
hipótese
fonte
13

Faltando neste visão geral é a CJfunção - do-pacote. Usando:

library(data.table)
CJ(a, b, unique = TRUE)

dá:

      a          b
 1: ABC 2012-05-01
 2: ABC 2012-05-02
 3: ABC 2012-05-03
 4: ABC 2012-05-04
 5: ABC 2012-05-05
 6: DEF 2012-05-01
 7: DEF 2012-05-02
 8: DEF 2012-05-03
 9: DEF 2012-05-04
10: DEF 2012-05-05
11: GHI 2012-05-01
12: GHI 2012-05-02
13: GHI 2012-05-03
14: GHI 2012-05-04
15: GHI 2012-05-05

NOTA: desde a versão 1.12.2, CJas colunas resultantes são autonames (veja também aqui e aqui ).

Jaap
fonte
4

Desde a versão 1.0.0, tidyroferece sua própria versão do expand.grid(). Ele completa a família existente de expand(), nesting()e crossing()com uma função de baixo nível que funciona com vetores .

Quando comparado com base::expand.grid():

Varia o primeiro elemento mais rápido. Nunca converte strings em fatores. Não adiciona nenhum atributo adicional. Retorna um tibble, não um quadro de dados. Pode expandir qualquer vetor generalizado, incluindo frames de dados.

a <- c("ABC", "DEF", "GHI")
b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

tidyr::expand_grid(a, b)

   a     b         
   <chr> <chr>     
 1 ABC   2012-05-01
 2 ABC   2012-05-02
 3 ABC   2012-05-03
 4 ABC   2012-05-04
 5 ABC   2012-05-05
 6 DEF   2012-05-01
 7 DEF   2012-05-02
 8 DEF   2012-05-03
 9 DEF   2012-05-04
10 DEF   2012-05-05
11 GHI   2012-05-01
12 GHI   2012-05-02
13 GHI   2012-05-03
14 GHI   2012-05-04
15 GHI   2012-05-05
tmfmnk
fonte
2

você pode usar a função de ordem para classificar qualquer número de colunas. pelo seu exemplo

df <- expand.grid(a,b)
> df
   Var1       Var2
1   ABC 2012-05-01
2   DEF 2012-05-01
3   GHI 2012-05-01
4   ABC 2012-05-02
5   DEF 2012-05-02
6   GHI 2012-05-02
7   ABC 2012-05-03
8   DEF 2012-05-03
9   GHI 2012-05-03
10  ABC 2012-05-04
11  DEF 2012-05-04
12  GHI 2012-05-04
13  ABC 2012-05-05
14  DEF 2012-05-05
15  GHI 2012-05-05

> df[order( df[,1], df[,2] ),] 
   Var1       Var2
1   ABC 2012-05-01
4   ABC 2012-05-02
7   ABC 2012-05-03
10  ABC 2012-05-04
13  ABC 2012-05-05
2   DEF 2012-05-01
5   DEF 2012-05-02
8   DEF 2012-05-03
11  DEF 2012-05-04
14  DEF 2012-05-05
3   GHI 2012-05-01
6   GHI 2012-05-02
9   GHI 2012-05-03
12  GHI 2012-05-04
15  GHI 2012-05-05`
Izan
fonte