python - create - pandas dataframe to numpy array
Convierta el marco de datos pandas en una matriz numpy, preservando el índice (11)
Aquí está mi enfoque para hacer una matriz de estructura de un marco de datos de pandas.
Crear el marco de datos
import pandas as pd
import numpy as np
import six
NaN = float(''nan'')
ID = [1, 2, 3, 4, 5, 6, 7]
A = [NaN, NaN, NaN, 0.1, 0.1, 0.1, 0.1]
B = [0.2, NaN, 0.2, 0.2, 0.2, NaN, NaN]
C = [NaN, 0.5, 0.5, NaN, 0.5, 0.5, NaN]
columns = {''A'':A, ''B'':B, ''C'':C}
df = pd.DataFrame(columns, index=ID)
df.index.name = ''ID''
print(df)
A B C
ID
1 NaN 0.2 NaN
2 NaN NaN 0.5
3 NaN 0.2 0.5
4 0.1 0.2 NaN
5 0.1 0.2 0.5
6 0.1 NaN 0.5
7 0.1 NaN NaN
Defina la función para crear una matriz de estructura numpy (no una matriz de registro) a partir de un marco de datos de pandas.
def df_to_sarray(df):
"""
Convert a pandas DataFrame object to a numpy structured array.
This is functionally equivalent to but more efficient than
np.array(df.to_array())
:param df: the data frame to convert
:return: a numpy structured array representation of df
"""
v = df.values
cols = df.columns
if six.PY2: # python 2 needs .encode() but 3 does not
types = [(cols[i].encode(), df[k].dtype.type) for (i, k) in enumerate(cols)]
else:
types = [(cols[i], df[k].dtype.type) for (i, k) in enumerate(cols)]
dtype = np.dtype(types)
z = np.zeros(v.shape[0], dtype)
for (i, k) in enumerate(z.dtype.names):
z[k] = v[:, i]
return z
Use reset_index
para crear un nuevo marco de datos que incluya el índice como parte de sus datos. Convertir ese marco de datos en una matriz de estructura.
sa = df_to_sarray(df.reset_index())
sa
array([(1L, nan, 0.2, nan), (2L, nan, nan, 0.5), (3L, nan, 0.2, 0.5),
(4L, 0.1, 0.2, nan), (5L, 0.1, 0.2, 0.5), (6L, 0.1, nan, 0.5),
(7L, 0.1, nan, nan)],
dtype=[(''ID'', ''<i8''), (''A'', ''<f8''), (''B'', ''<f8''), (''C'', ''<f8'')])
EDITAR: Se actualizó df_to_sarray para evitar errores al llamar a .encode () con python 3. Gracias a Joseph Garvin y halcyon por su comentario y solución.
Estoy interesado en saber cómo convertir un marco de datos de pandas en una matriz numpy, incluido el índice, y establecer los tipos de datos.
marco de datos:
import numpy as np
import pandas as pd
index = [1, 2, 3, 4, 5, 6, 7]
a = [np.nan, np.nan, np.nan, 0.1, 0.1, 0.1, 0.1]
b = [0.2, np.nan, 0.2, 0.2, 0.2, np.nan, np.nan]
c = [np.nan, 0.5, 0.5, np.nan, 0.5, 0.5, np.nan]
df = pd.DataFrame({''A'': a, ''B'': b, ''C'': c}, index=index)
df = df.rename_axis(''ID'')
da
label A B C
ID
1 NaN 0.2 NaN
2 NaN NaN 0.5
3 NaN 0.2 0.5
4 0.1 0.2 NaN
5 0.1 0.2 0.5
6 0.1 NaN 0.5
7 0.1 NaN NaN
convertir df a matriz devuelve:
array([[ nan, 0.2, nan],
[ nan, nan, 0.5],
[ nan, 0.2, 0.5],
[ 0.1, 0.2, nan],
[ 0.1, 0.2, 0.5],
[ 0.1, nan, 0.5],
[ 0.1, nan, nan]])
Sin embargo, me gustaría:
array([[ 1, nan, 0.2, nan],
[ 2, nan, nan, 0.5],
[ 3, nan, 0.2, 0.5],
[ 4, 0.1, 0.2, nan],
[ 5, 0.1, 0.2, 0.5],
[ 6, 0.1, nan, 0.5],
[ 7, 0.1, nan, nan]],
dtype=[(''ID'', ''<i4''), (''A'', ''<f8''), (''B'', ''<f8''), (''B'', ''<f8'')])
(o similar)
¿Alguna sugerencia sobre cómo lograr esto? (No sé si necesito una matriz 1D o 2D en este punto). He visto algunas publicaciones que se refieren a esto, pero nada relacionado específicamente con el dataframe.index.
Estoy escribiendo el disco de marco de datos usando to_csv (y lo estoy leyendo para crear una matriz) como solución alternativa, pero preferiría algo más elocuente que mi nuevo kludging para pandas.
Dos formas de convertir el marco de datos a su representación de matriz Numpy.
mah_np_array = df.as_matrix(columns=None)
mah_np_array = df.values
Doc: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.as_matrix.html
En respuesta a la respuesta de Meteore, encontré el código.
df.index = df.index.astype(''i8'')
no funciona para mi Así que puse mi código aquí para la conveniencia de otros atrapados en este problema.
city_cluster_df = pd.read_csv(text_filepath, encoding=''utf-8'')
# the field ''city_en'' is a string, when converted to Numpy array, it will be an object
city_cluster_arr = city_cluster_df[[''city_en'',''lat'',''lon'',''cluster'',''cluster_filtered'']].to_records()
descr=city_cluster_arr.dtype.descr
# change the field ''city_en'' to string type (the index for ''city_en'' here is 1 because before the field is the row index of dataframe)
descr[1]=(descr[1][0], "S20")
newArr=city_cluster_arr.astype(np.dtype(descr))
Gracias por la respuesta de Phil, es genial.
responder a
no me funciona, error: TypeError: tipo de datos no entendido - Joseph Garvin 13 de febrero a las 17:55
Uso python 3 y obtengo el mismo error. y luego elimino .encode (), luego la expresión es la siguiente.
types = [(cols[i], df[k].dtype.type) for (i, k) in enumerate(cols)]
entonces funciona.
Pandas tiene algo construido en ...
numpy_matrix = df.as_matrix()
da
array([[nan, 0.2, nan],
[nan, nan, 0.5],
[nan, 0.2, 0.5],
[0.1, 0.2, nan],
[0.1, 0.2, 0.5],
[0.1, nan, 0.5],
[0.1, nan, nan]])
Para convertir un marco de datos de pandas (df) en un ndarray numpy, use este código:
df = df.values
df ahora se convierte en el ndarray numpy:
array([[nan, 0.2, nan],
[nan, nan, 0.5],
[nan, 0.2, 0.5],
[0.1, 0.2, nan],
[0.1, 0.2, 0.5],
[0.1, nan, 0.5],
[0.1, nan, nan]])
Parece que df.to_records()
funcionará para usted. Se solicitó la característica exacta que estaba buscando y to_records
señaló como una alternativa.
Intenté esto localmente usando su ejemplo, y esa llamada produce algo muy similar a la salida que estaba buscando:
rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5),
(4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5),
(7, 0.1, nan, nan)],
dtype=[(u''ID'', ''<i8''), (u''A'', ''<f8''), (u''B'', ''<f8''), (u''C'', ''<f8'')])
Tenga en cuenta que esto es un recarray
lugar de una array
. Puede mover el resultado a una matriz numpy normal llamando a su constructor como np.array(df.to_records())
.
Puedes usar el método to_records
, pero to_records
jugar un poco con los dtypes si no son lo que quieres desde el principio. En mi caso, habiendo copiado su DF de una cadena, el tipo de índice es una cadena (representada por un tipo de object
en pandas):
In [102]: df
Out[102]:
label A B C
ID
1 NaN 0.2 NaN
2 NaN NaN 0.5
3 NaN 0.2 0.5
4 0.1 0.2 NaN
5 0.1 0.2 0.5
6 0.1 NaN 0.5
7 0.1 NaN NaN
In [103]: df.index.dtype
Out[103]: dtype(''object'')
In [104]: df.to_records()
Out[104]:
rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5),
(4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5),
(7, 0.1, nan, nan)],
dtype=[(''index'', ''|O8''), (''A'', ''<f8''), (''B'', ''<f8''), (''C'', ''<f8'')])
In [106]: df.to_records().dtype
Out[106]: dtype([(''index'', ''|O8''), (''A'', ''<f8''), (''B'', ''<f8''), (''C'', ''<f8'')])
La conversión del tipo de recarray no funciona para mí, pero ya se puede hacer esto en Pandas:
In [109]: df.index = df.index.astype(''i8'')
In [111]: df.to_records().view([(''ID'', ''<i8''), (''A'', ''<f8''), (''B'', ''<f8''), (''C'', ''<f8'')])
Out[111]:
rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5),
(4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5),
(7, 0.1, nan, nan)],
dtype=[(''ID'', ''<i8''), (''A'', ''<f8''), (''B'', ''<f8''), (''C'', ''<f8'')])
Tenga en cuenta que Pandas no establece correctamente el nombre del índice (a ID
) en la matriz de registros exportados (¿un error?), Por lo que nos beneficiamos de la conversión de tipos para corregir eso también.
En este momento, Pandas solo tiene enteros de 8 bytes, i8
, y flotantes, f8
(ver este issue ).
Simplemente encadenaría las DataFrame.reset_index() y DataFrame.values para obtener la representación de Numpy del marco de datos, incluido el índice:
In [8]: df
Out[8]:
A B C
0 -0.982726 0.150726 0.691625
1 0.617297 -0.471879 0.505547
2 0.417123 -1.356803 -1.013499
3 -0.166363 -0.957758 1.178659
4 -0.164103 0.074516 -0.674325
5 -0.340169 -0.293698 1.231791
6 -1.062825 0.556273 1.508058
7 0.959610 0.247539 0.091333
[8 rows x 3 columns]
In [9]: df.reset_index().values
Out[9]:
array([[ 0. , -0.98272574, 0.150726 , 0.69162512],
[ 1. , 0.61729734, -0.47187926, 0.50554728],
[ 2. , 0.4171228 , -1.35680324, -1.01349922],
[ 3. , -0.16636303, -0.95775849, 1.17865945],
[ 4. , -0.16410334, 0.0745164 , -0.67432474],
[ 5. , -0.34016865, -0.29369841, 1.23179064],
[ 6. , -1.06282542, 0.55627285, 1.50805754],
[ 7. , 0.95961001, 0.24753911, 0.09133339]])
Para obtener los dtypes necesitaríamos transformar esta ndarray en una matriz estructurada usando la view :
In [10]: df.reset_index().values.ravel().view(dtype=[(''index'', int), (''A'', float), (''B'', float), (''C'', float)])
Out[10]:
array([( 0, -0.98272574, 0.150726 , 0.69162512),
( 1, 0.61729734, -0.47187926, 0.50554728),
( 2, 0.4171228 , -1.35680324, -1.01349922),
( 3, -0.16636303, -0.95775849, 1.17865945),
( 4, -0.16410334, 0.0745164 , -0.67432474),
( 5, -0.34016865, -0.29369841, 1.23179064),
( 6, -1.06282542, 0.55627285, 1.50805754),
( 7, 0.95961001, 0.24753911, 0.09133339),
dtype=[(''index'', ''<i8''), (''A'', ''<f8''), (''B'', ''<f8''), (''C'', ''<f8'')])
Solo tuve un problema similar al exportar desde la tabla de dataframe a arcgis y tropezé con una solución de usgs ( https://my.usgs.gov/confluence/display/cdi/pandas.DataFrame+to+ArcGIS+Table ). En resumen su problema tiene una solución similar:
df
Out[109]:
A B C
ID
1 NaN 0.2 NaN
2 NaN NaN 0.5
3 NaN 0.2 0.5
4 0.1 0.2 NaN
5 0.1 0.2 0.5
6 0.1 NaN 0.5
7 0.1 NaN NaN
np_data = np.array(np.rec.fromrecords(df.values))
np_names = df.dtypes.index.tolist()
np_data.dtype.names = tuple([name.encode(''UTF8'') for name in np_names])
np_data
Out[113]:
array([( nan, 0.2, nan), ( nan, nan, 0.5), ( nan, 0.2, 0.5),
( 0.1, 0.2, nan), ( 0.1, 0.2, 0.5), ( 0.1, nan, 0.5),
( 0.1, nan, nan)],
dtype=(numpy.record, [(''A'', ''<f8''), (''B'', ''<f8''), (''C'', ''<f8'')]))
Una forma más simple de ejemplo DataFrame: df
df =
gbm nnet reg
0 12.097439 12.047437 12.100953
1 12.109811 12.070209 12.095288
2 11.720734 11.622139 11.740523
3 11.824557 11.926414 11.926527
4 11.800868 11.727730 11.729737
5 12.490984 12.502440 12.530894
UTILIZAR:
np.array(df.to_records().view(type=np.matrix))
OBTENER:
array([[(0, 12.097439 , 12.047437, 12.10095324),
(1, 12.10981081, 12.070209, 12.09528824),
(2, 11.72073428, 11.622139, 11.74052253),
(3, 11.82455653, 11.926414, 11.92652727),
(4, 11.80086775, 11.72773 , 11.72973699),
(5, 12.49098389, 12.50244 , 12.53089367)]],
dtype=(numpy.record, [(''index'', ''<i8''), (''gbm'', ''<f8''), (''nnet'', ''<f4''),
(''reg'', ''<f8'')]))