example - R expand.grid() funciona en Python
expand grid r example (7)
¿Has probado product
de itertools
? Bastante más fácil de usar que algunos de estos métodos en mi opinión (con la excepción de pandas
y meshgrid
). Tenga en cuenta que esta configuración realmente arrastra todos los elementos del iterador a una lista, y luego los convierte en un ndarray
así que tenga cuidado con las dimensiones más altas o elimine np.asarray(list(combs))
para las cuadrículas de dimensiones superiores a menos que desee Si se queda sin memoria, puede consultar el iterador para combinaciones específicas. meshgrid
embargo, recomiendo altamente meshgrid
para esto:
#Generate square grid from axis
from itertools import product
import numpy as np
a=np.array(list(range(3)))+1 # axis with offset for 0 base index to 1
points=product(a,repeat=2) #only allow repeats for (i,j), (j,i) pairs with i!=j
np.asarray(list(points)) #convert to ndarray
Y obtengo la siguiente salida de esto:
array([[1, 1],
[1, 2],
[1, 3],
[2, 1],
[2, 2],
[2, 3],
[3, 1],
[3, 2],
[3, 3]])
¿Existe una función de Python similar a la función expand.grid () en R? Gracias por adelantado.
(EDITAR) A continuación se muestra la descripción de esta función R y un ejemplo.
Create a Data Frame from All Combinations of Factors
Description:
Create a data frame from all combinations of the supplied vectors
or factors.
> x <- 1:3
> y <- 1:3
> expand.grid(x,y)
Var1 Var2
1 1 1
2 2 1
3 3 1
4 1 2
5 2 2
6 3 2
7 1 3
8 2 3
9 3 3
(EDIT2) A continuación se muestra un ejemplo con el paquete rpy. Me gustaría obtener el mismo objeto de salida pero sin usar R:
>>> from rpy import *
>>> a = [1,2,3]
>>> b = [5,7,9]
>>> r.assign("a",a)
[1, 2, 3]
>>> r.assign("b",b)
[5, 7, 9]
>>> r("expand.grid(a,b)")
{''Var1'': [1, 2, 3, 1, 2, 3, 1, 2, 3], ''Var2'': [5, 5, 5, 7, 7, 7, 9, 9, 9]}
EDITAR 02/09/2012: Estoy realmente perdido con Python. El código de Lev Levitsky que figura en su respuesta no me funciona:
>>> a = [1,2,3]
>>> b = [5,7,9]
>>> expandgrid(a, b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in expandgrid
NameError: global name ''itertools'' is not defined
Sin embargo, el módulo itertools parece estar instalado (escribir from itertools import *
no devuelve ningún mensaje de error)
Aquí hay otra versión que devuelve un pandas.DataFrame:
import itertools as it
import pandas as pd
def expand_grid(*args, **kwargs):
columns = []
lst = []
if args:
columns += xrange(len(args))
lst += args
if kwargs:
columns += kwargs.iterkeys()
lst += kwargs.itervalues()
return pd.DataFrame(list(it.product(*lst)), columns=columns)
print expand_grid([0,1], [1,2,3])
print expand_grid(a=[0,1], b=[1,2,3])
print expand_grid([0,1], b=[1,2,3])
Aquí hay un ejemplo que da un resultado similar a lo que necesitas:
import itertools
def expandgrid(*itrs):
product = list(itertools.product(*itrs))
return {''Var{}''.format(i+1):[x[i] for x in product] for i in range(len(itrs))}
>>> a = [1,2,3]
>>> b = [5,7,9]
>>> expandgrid(a, b)
{''Var1'': [1, 1, 1, 2, 2, 2, 3, 3, 3], ''Var2'': [5, 7, 9, 5, 7, 9, 5, 7, 9]}
La diferencia está relacionada con el hecho de que en itertools.product
itertools.product . Puede modificar la función ordenando la lista de product
inteligente si es importante.
La documentación de pandas define una función expand_grid
:
def expand_grid(data_dict):
"""Create a dataframe from every combination of given values."""
rows = itertools.product(*data_dict.values())
return pd.DataFrame.from_records(rows, columns=data_dict.keys())
Para que este código funcione, necesitará las siguientes dos importaciones:
import itertools
import pandas as pd
La salida es un pandas.DataFrame
que es el objeto más comparable en Python a un R data.frame
.
Me he preguntado esto por un tiempo y no estoy satisfecho con las soluciones presentadas hasta ahora, por lo que se me ocurrió la mía, que es considerablemente más simple (pero probablemente más lenta). La función utiliza numpy.meshgrid para hacer la cuadrícula, luego aplana las cuadrículas en matrices 1d y las pone juntas:
def expand_grid(x, y):
xG, yG = np.meshgrid(x, y) # create the actual grid
xG = xG.flatten() # make the grid 1d
yG = yG.flatten() # same
return pd.DataFrame({''x'':xG, ''y'':yG}) # return a dataframe
Por ejemplo:
import numpy as np
import pandas as pd
p, q = np.linspace(1, 10, 10), np.linspace(1, 10, 10)
def expand_grid(x, y):
xG, yG = np.meshgrid(x, y) # create the actual grid
xG = xG.flatten() # make the grid 1d
yG = yG.flatten() # same
return pd.DataFrame({''x'':xG, ''y'':yG})
print expand_grid(p, q).head(n = 20)
Sé que esta es una publicación antigua, ¡pero pensé que compartiría mi versión simple!
Solo usa la lista de comprensión:
>>> [(x, y) for x in range(5) for y in range(5)]
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
convertir a la matriz numpy si lo desea:
>>> import numpy as np
>>> x = np.array([(x, y) for x in range(5) for y in range(5)])
>>> x.shape
(25, 2)
He probado hasta 10000 x 10000 y el rendimiento de python es comparable al de expand.grid en R. Usar una tupla (x, y) es aproximadamente un 40% más rápido que usar una lista [x, y] en la comprensión.
O...Alrededor de 3 veces más rápido con np.meshgrid y mucho menos memoria.
%timeit np.array(np.meshgrid(range(10000), range(10000))).reshape(2, 100000000).T
1 loops, best of 3: 736 ms per loop
en R:
> system.time(expand.grid(1:10000, 1:10000))
user system elapsed
1.991 0.416 2.424
Tenga en cuenta que R tiene matrices basadas en 1, mientras que Python está basado en 0.
product
de itertools
es la clave de su solución. Produce un producto cartesiano de los insumos.
from itertools import product
def expand_grid(dictionary):
return pd.DataFrame([row for row in product(*dictionary.values())],
columns=dictionary.keys())
dictionary = {''color'': [''red'', ''green'', ''blue''],
''vehicle'': [''car'', ''van'', ''truck''],
''cylinders'': [6, 8]}
>>> expand_grid(dictionary)
color cylinders vehicle
0 red 6 car
1 red 6 van
2 red 6 truck
3 red 8 car
4 red 8 van
5 red 8 truck
6 green 6 car
7 green 6 van
8 green 6 truck
9 green 8 car
10 green 8 van
11 green 8 truck
12 blue 6 car
13 blue 6 van
14 blue 6 truck
15 blue 8 car
16 blue 8 van
17 blue 8 truck