Combinación única de todos los elementos de dos (o más) vectores

95

Estoy tratando de crear una combinación única de todos los elementos de dos vectores de diferente tamaño en R.

Por ejemplo, el primer vector es

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

y el segundo son las fechas almacenadas como cadenas actualmente

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

Necesito crear un marco de datos con dos columnas 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

Entonces, básicamente, estoy buscando una combinación única al considerar todos los elementos de un vector (a) yuxtapuestos con todos los elementos del segundo vector (b).

Una solución ideal se generalizaría a más vectores de entrada.


Ver también:
Cómo generar una matriz de combinaciones

Godel
fuente

Respuestas:

139

esto tal vez lo que buscas

> 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

Si el orden resultante no es el que desea, puede ordenar después. Si nombra los argumentos a expand.grid, se convertirán en nombres de columna:

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

Y expand.gridgeneraliza a cualquier número de columnas de entrada.

shhhhimhuntingrabbits
fuente
4
Y sin necesidad plyrde hacer una clasificación:result <- expand.grid(a=a,b=b); result <- result[order(result$a,result$b),];
thelatemail
¿Alguien con más reputación que yo puede aceptar esta respuesta?
Josh
Si el orden y los nombres deben ser como en la pregunta:expand.grid(b=b,a=a)[2:1]
GKi
Tenga en cuenta que el título es Combinaciones únicas: esta respuesta resuelve el problema de OP, pero si las 2 columnas son del mismo tipo de datos y aplica expand.grid, tendrá permutaciones únicas, no combinaciones únicas
Brent
28

El tidyrpaquete proporciona una buena alternativa crossing, que funciona mejor que la expand.gridfunción clásica porque (1) las cadenas no se convierten en factores y (2) la clasificación es más 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ótesis
fuente
13

Falta en esto descripción general es la CJfunción de la-paquete. Utilizando:

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

da:

      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: dado que la versión 1.12.2 nombra CJautomáticamente las columnas resultantes (consulte también aquí y aquí ).

Jaap
fuente
4

Desde la versión 1.0.0, tidyrofrece su propia versión de expand.grid(). Se completa la familia existente de expand(), nesting()y crossing()con una función de bajo nivel que trabaja con vectores .

En comparación con base::expand.grid():

Varía el primer elemento más rápido. Nunca convierte cadenas en factores. No agrega ningún atributo adicional. Devuelve un tibble, no un marco de datos. Puede expandir cualquier vector generalizado, incluidos los marcos de datos.

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
fuente
3

puede utilizar la función de orden para ordenar cualquier número de columnas. por tu ejemplo

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
fuente