Agregue una matriz numpy como columna al marco de datos de Pandas

82

Tengo un objeto de marco de datos de Pandas de forma (X, Y) que se ve así:

[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]

y una matriz dispersa numpy (CSC) de forma (X, Z) que se parece a esto

[[0, 1, 0],
[0, 0, 1],
[1, 0, 0]]

¿Cómo puedo agregar el contenido de la matriz al marco de datos en una nueva columna con nombre de modo que el marco de datos termine así:

[[1, 2, 3, [0, 1, 0]],
[4, 5, 6, [0, 0, 1]],
[7, 8, 9, [1, 0, 0]]]

Observe que el marco de datos ahora tiene forma (X, Y + 1) y las filas de la matriz son elementos del marco de datos.

Mihai Damian
fuente
2
Se desaconseja este tipo de anidación. ¿Por qué necesitas hacer esto?
Phillip Cloud
Vea esta pregunta: stackoverflow.com/q/18641148/564538
Phillip Cloud
Quiero conservar la posibilidad de seleccionar el contenido anterior de la matriz con un solo nombre de columna después de la combinación.
Mihai Damian
¿Por qué no usas dos DataFrames?
Phillip Cloud

Respuestas:

78
import numpy as np
import pandas as pd
import scipy.sparse as sparse

df = pd.DataFrame(np.arange(1,10).reshape(3,3))
arr = sparse.coo_matrix(([1,1,1], ([0,1,2], [1,2,0])), shape=(3,3))
df['newcol'] = arr.toarray().tolist()
print(df)

rendimientos

   0  1  2     newcol
0  1  2  3  [0, 1, 0]
1  4  5  6  [0, 0, 1]
2  7  8  9  [1, 0, 0]
unutbu
fuente
6
Supongo que realmente no podemos proporcionar zapatos a prueba de balas para los usuarios que insisten en hacer cosas como esta: /
Phillip Cloud
6
Hay cosas interesantes que puedes hacer con una columna de listas , así que prefiero no asumir que esto es necesariamente una mala idea. Aunque estoy de acuerdo, hay muchas posibilidades de que lo sea.
unutbu
1
Ese es un maravilloso ejemplo de pandasflexibilidad. En el caso de esta pregunta, los datos ya son de tipo numérico homogéneo con filas de igual forma, mientras que en ese ejemplo son listde diferente longitud. Estoy de acuerdo en que hay cosas interesantes que puedes hacer. Sin embargo, cuando ya tiene una matriz, ¿por qué convertirla en una lista de listas?
Phillip Cloud
1
Lo "interesante" es ... ¡hacer que ya no sea una columna de listas (así que es útil)!
Andy Hayden
51
El mundo es un lugar mejor cuando a las personas creativas se les permite hacer cosas que todos los demás creen que son estúpidas. :)
unutbu
10

Considere usar una estructura de datos de mayor dimensión (un Panel ), en lugar de almacenar una matriz en su columna:

In [11]: p = pd.Panel({'df': df, 'csc': csc})

In [12]: p.df
Out[12]: 
   0  1  2
0  1  2  3
1  4  5  6
2  7  8  9

In [13]: p.csc
Out[13]: 
   0  1  2
0  0  1  0
1  0  0  1
2  1  0  0

Mire las secciones transversales, etc., etc., etc.

In [14]: p.xs(0)
Out[14]: 
   csc  df
0    0   1
1    1   2
2    0   3

Consulte los documentos para obtener más información sobre los paneles .

Andy Hayden
fuente
11
El panel ahora está obsoleto
guhur
Sí, generalmente se recomienda MultiIndex en la actualidad. Creado, por ejemplo, a través de pd.concat([df, csc], axis=1, keys=["df", "csc"]).
Andy Hayden
A = np.eye(3); df = pd.concat( [A,A], axis=1 )-> TypeError: ¿no se puede concatenar un objeto que no sea NDFrame en 20.2? (Una wiki de "pandas-deprecated-now-use-this" sería bueno.)
denis
@denis tryA = pd.DataFrame(np.eye(3)); df = pd.concat( [A,A], axis=1, keys=["A", "B"] )
Andy Hayden
Gracias, df.columns MultiIndex(levels=[[u'A', u'B'], [0, 1, 2]](da una palmada en la frente)
denis
3

Aquí hay otro ejemplo:

import numpy as np
import pandas as pd

""" This just creates a list of touples, and each element of the touple is an array"""
a = [ (np.random.randint(1,10,10), np.array([0,1,2,3,4,5,6,7,8,9]))  for i in 
range(0,10) ]

""" Panda DataFrame will allocate each of the arrays , contained as a touple 
element , as column"""
df = pd.DataFrame(data =a,columns=['random_num','sequential_num'])

El secreto en general es asignar los datos en la forma a = [(array_11, array_12, ..., array_1n), ..., (array_m1, array_m2, ..., array_mn)] y panda DataFrame ordenará los datos en n columnas de matrices. Por supuesto, se podrían usar matrices de matrices en lugar de touples, en ese caso la forma sería: a = [[matriz_11, matriz_12, ..., matriz_1n], ..., [matriz_m1, matriz_m2, ..., matriz_mn ]]

Esta es la salida si imprime (df) desde el código anterior:

                       random_num                  sequential_num
0  [7, 9, 2, 2, 5, 3, 5, 3, 1, 4]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1  [8, 7, 9, 8, 1, 2, 2, 6, 6, 3]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2  [3, 4, 1, 2, 2, 1, 4, 2, 6, 1]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3  [3, 1, 1, 1, 6, 2, 8, 6, 7, 9]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4  [4, 2, 8, 5, 4, 1, 2, 2, 3, 3]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5  [3, 2, 7, 4, 1, 5, 1, 4, 6, 3]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
6  [5, 7, 3, 9, 7, 8, 4, 1, 3, 1]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7  [7, 4, 7, 6, 2, 6, 3, 2, 5, 6]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8  [3, 1, 6, 3, 2, 1, 5, 2, 2, 9]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9  [7, 2, 3, 9, 5, 5, 8, 6, 9, 8]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Otra variación del ejemplo anterior:

b = [ (i,"text",[14, 5,], np.array([0,1,2,3,4,5,6,7,8,9]))  for i in 
range(0,10) ]
df = pd.DataFrame(data=b,columns=['Number','Text','2Elemnt_array','10Element_array'])

Salida de df:

   Number  Text 2Elemnt_array                 10Element_array
0       0  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1       1  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2       2  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3       3  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4       4  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5       5  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
6       6  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7       7  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8       8  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9       9  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Si desea agregar otras columnas de matrices, entonces:

df['3Element_array']=[([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3])]

La salida final de df será:

   Number  Text 2Elemnt_array                 10Element_array 3Element_array
0       0  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
1       1  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
2       2  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
3       3  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
4       4  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
5       5  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
6       6  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
7       7  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
8       8  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
9       9  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
Jorge Vilchis
fuente
0

Para matrices numpy normales, para agregar y recuperar del marco de datos, puede hacer esto. Se basa en la respuesta anterior que me confundió debido a la parte escasa cuando solo tenía una matriz numpy normal.

import numpy as np
import pandas as pd

df = pd.DataFrame({'b':range(10)}) # target dataframe
a = np.random.normal(size=(10,2)) # numpy array
df['a']=a.tolist() # save array
np.array(df['a'].tolist()) # retrieve array
citynorman
fuente
0
df = pd.DataFrame(np.arange(1,10).reshape(3,3))
df['newcol'] = pd.Series(your_2d_numpy_array)
Max Bileschi
fuente