“Fusionar” una gran cantidad de matrices junto con una dimensión común

Tengo dos matrices, correspondientes a los puntos de datos (x,y1) y (x,y2) :

  x | y1 ------------ 0 | 0 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 x | y2 ---------------- 0.5 | 0.5 1.5 | 1.5 2.5 | 2.5 3.5 | 3.5 4.5 | 4.5 5.5 | 5.5 

Me gustaría crear una nueva matriz que combine los valores de x en una sola columna y tenga NaN s en las columnas y1 , y2 apropiadas:

  x | y1 | y2 ----------------------------- 0 | 0 | NaN 0.5 | NaN | 0.5 1 | 0 | NaN 1.5 | NaN | 1.5 ... | ... | ... 5 | 5 | NaN 5.5 | NaN | 5.5 

¿Hay una forma fácil de hacer esto? Soy nuevo en Python y NumPy (proveniente de MATLAB) y no estoy seguro de cómo podría comenzar con esto. (Para referencia, mi enfoque de esto en MATLAB es simplemente usar una outerjoin contra dos tablas que se generan con array2table ).

Si puede cargar sus datos en marcos de datos de pandas separados, esto se vuelve simple.

 df x y1 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 df2 x y2 0 0.5 0.5 1 1.5 1.5 2 2.5 2.5 3 3.5 3.5 4 4.5 4.5 5 5.5 5.5 

Realice una merge externa y ordene en la columna x .

 df = df.merge(df2, how='outer').sort_values('x') df x y1 y2 0 0 0 NaN 6 0.5 NaN 0.5 1 1 1 NaN 7 1.5 NaN 1.5 2 2 2 NaN 8 2.5 NaN 2.5 3 3 3 NaN 9 3.5 NaN 3.5 4 4 4 NaN 10 4.5 NaN 4.5 5 5 5 NaN 11 5.5 NaN 5.5 

Si desea una matriz, llame a .values en el resultado:

 df.values array([[0.0, 0.0, nan], [0.5, nan, 0.5], [1.0, 1.0, nan], [1.5, nan, 1.5], [2.0, 2.0, nan], [2.5, nan, 2.5], [3.0, 3.0, nan], [3.5, nan, 3.5], [4.0, 4.0, nan], [4.5, nan, 4.5], [5.0, 5.0, nan], [5.5, nan, 5.5]], dtype=object) 

Aquí hay un bash con un simple numpy . Crea una matriz con 3 columnas y tantas filas como a1 + a2 . Escribe a1 y a2 en las columnas, y ordena las filas por su primer valor.

Tenga en cuenta que solo funciona si los valores de x son disjuntos:

 import numpy as np x = np.arange(6) # array([0, 1, 2, 3, 4, 5]) a1 = np.vstack((x,x)).T # array([[0, 0], # [1, 1], # [2, 2], # [3, 3], # [4, 4], # [5, 5]]) a2 = a1 + 0.5 # array([[ 0.5, 0.5], # [ 1.5, 1.5], # [ 2.5, 2.5], # [ 3.5, 3.5], # [ 4.5, 4.5], # [ 5.5, 5.5]]) m = np.empty((12, 3)) m[:] = np.nan # array([[ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan]]) m[:6, :2] = a1 # array([[ 0., 0., nan], # [ 1., 1., nan], # [ 2., 2., nan], # [ 3., 3., nan], # [ 4., 4., nan], # [ 5., 5., nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan], # [ nan, nan, nan]]) m[6:, ::2] = a2 # array([[ 0. , 0. , nan], # [ 1. , 1. , nan], # [ 2. , 2. , nan], # [ 3. , 3. , nan], # [ 4. , 4. , nan], # [ 5. , 5. , nan], # [ 0.5, nan, 0.5], # [ 1.5, nan, 1.5], # [ 2.5, nan, 2.5], # [ 3.5, nan, 3.5], # [ 4.5, nan, 4.5], # [ 5.5, nan, 5.5]]) m[m[:,0].argsort()] # array([[ 0. , 0. , nan], # [ 0.5, nan, 0.5], # [ 1. , 1. , nan], # [ 1.5, nan, 1.5], # [ 2. , 2. , nan], # [ 2.5, nan, 2.5], # [ 3. , 3. , nan], # [ 3.5, nan, 3.5], # [ 4. , 4. , nan], # [ 4.5, nan, 4.5], # [ 5. , 5. , nan], # [ 5.5, nan, 5.5]]) 

Usar pandas es el método correcto aquí.

Un enfoque de matriz estructurada (incompleto):

Introduzca una biblioteca especial de recfunctions:

 In [441]: import numpy.lib.recfunctions as rf 

Definir dos matrices estructuradas.

 In [442]: A = np.zeros((6,),[('x',int),('y',int)]) 

Vaya, las keys in ‘x keys in B are float, so for consistency, let's make the ‘ también floten. No mezcle flotadores e ints innecesariamente.

 In [446]: A = np.zeros((6,),[('x',float),('y',int)]) In [447]: A['x']=np.arange(6) In [448]: A['y']=np.arange(6) In [449]: A Out[449]: array([( 0., 0), ( 1., 1), ( 2., 2), ( 3., 3), ( 4., 4), ( 5., 5)], dtype=[('x', ' 

Mire los documentos de la función rf.join_by :

 In [454]: rf.join_by? 

Hacer una unión outer :

 In [457]: rf.join_by('x',A,B,'outer') Out[457]: masked_array(data = [(0.0, 0, --) (0.5, --, 0.5) (1.0, 1, --) (1.5, --, 1.5) (2.0, 2, --) (2.5, --, 2.5) (3.0, 3, --) (3.5, --, 3.5) (4.0, 4, --) (4.5, --, 4.5) (5.0, 5, --) (5.5, --, 5.5)], mask = [(False, False, True) (False, True, False) (False, False, True) (False, True, False) (False, False, True) (False, True, False) (False, False, True) (False, True, False) (False, False, True) (False, True, False) (False, False, True) (False, True, False)], fill_value = ( 1.00000000e+20, 999999, 1.00000000e+20), dtype = [('x', ' 

El resultado es una matriz enmascarada, con los valores faltantes enmascarados.

Lo mismo, pero con el enmascaramiento desactivado:

 In [460]: rf.join_by('x',A,B,'outer',usemask=False) Out[460]: array([( 0. , 0, 1.00000000e+20), ( 0.5, 999999, 5.00000000e-01), ( 1. , 1, 1.00000000e+20), ( 1.5, 999999, 1.50000000e+00), ( 2. , 2, 1.00000000e+20), ( 2.5, 999999, 2.50000000e+00), ( 3. , 3, 1.00000000e+20), ( 3.5, 999999, 3.50000000e+00), ( 4. , 4, 1.00000000e+20), ( 4.5, 999999, 4.50000000e+00), ( 5. , 5, 1.00000000e+20), ( 5.5, 999999, 5.50000000e+00)], dtype=[('x', ' 

Ahora vemos los valores de relleno explícitamente. Debe haber una manera de reemplazar el 1e20 con np.nan . Reemplazar 999999 con nan es más complicado, ya que np.nan es un valor flotante, no entero.

Debajo de la portada, join_by es, probablemente, primero creando una matriz en blank con el tipo de join , y rellenando los campos uno por uno.

Teniendo en cuenta que es posible que no necesite pandas para nada más, esta es la solución estándar de biblioteca.

Lo dividiría en 2 listas de listas (suponiendo que el orden de los elementos es importante). Asi que

 xy1 = [[0,0],[1,1],......] xy2 = [[0.5,0.5],[1.5,1.5],.......] 

luego combine estas listas en una lista x agregando “NaN” alternativamente a la posición x [i] [1] o x [i] [2] para compensar los roles alternativos donde no están presentes. Cada x [i] [0] es la clave para un elemento del diccionario con los valores que son una lista con dos elementos mencionados anteriormente.

 finalx = {item[0]: item[1:] for item in x} finalx = {0:[0, 'NaN'],0.5:[NaN,0.5],......] 

Espero que esto ayude. Esto es más una dirección que una solución.