dataframes data create crear array python arrays numpy pandas type-conversion

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.



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'')]))