Je suis intéressé à savoir comment convertir un pandas dataframe en tableau NumPy.
trame de données:
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')
donne
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
Je voudrais convertir ceci en tableau NumPy, ainsi:
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]])
Comment puis-je faire ceci?
En prime, est-il possible de préserver les types, comme ceci?
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')])
ou similaire?
Pour convertir un pandas dataframe (df) en un Numpy ndarray, utilisez ce code:
df.values
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]])
Note : La méthode .as_matrix()
utilisée dans cette réponse est obsolète. Pandas 0.23.4 avertit:
La méthode
.as_matrix
sera supprimée dans une version ultérieure. Utilisez .values à la place.
Pandas a quelque chose construit dans ...
numpy_matrix = df.as_matrix()
donne
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]])
values
et as_matrix()
!À partir de la v0.24.0, nous avons découvert deux nouvelles méthodes préférées pour obtenir des matrices NumPy à partir de pandas objets:
to_numpy()
, défini sur les objets Index
, _Series,
_ et DataFrame
, etarray
, défini uniquement sur les objets Index
et Series
.Si vous visitez la documentation v0.24 pour .values
, vous verrez un gros avertissement rouge qui dit:
Avertissement: Nous vous recommandons d'utiliser
DataFrame.to_numpy()
à la place.
Voir cette section des notes de version v0.24. , et cette réponse pour plus d'informations.
to_numpy()
Dans l’esprit d’une meilleure cohérence dans l’API, une nouvelle méthode _to_numpy
_ a été introduite pour extraire le tableau NumPy sous-jacent à partir de DataFrames.
_# Setup.
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, index=['a', 'b', 'c'])
df
A B
a 1 4
b 2 5
c 3 6
_
_df.to_numpy()
array([[1, 4],
[2, 5],
[3, 6]])
_
Comme mentionné ci-dessus, cette méthode est également définie sur les objets Index
et Series
(voir ici ).
_df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
# array([1, 2, 3])
_
Par défaut, une vue est renvoyée, ainsi toute modification apportée affectera l'original.
_v = df.to_numpy()
v[0, 0] = -1
df
A B
a -1 4
b 2 5
c 3 6
_
Si vous avez plutôt besoin d'une copie, utilisez _to_numpy(copy=True
_);
_v = df.to_numpy(copy=True)
v[0, 0] = -123
df
A B
a 1 4
b 2 5
c 3 6
_
Si vous devez conserver le dtypes
...
Comme indiqué dans une autre réponse, DataFrame.to_records
est un bon moyen de procéder.
_df.to_records()
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])
_
Cela ne peut pas être fait avec _to_numpy
_, malheureusement. Toutefois, vous pouvez également utiliser _np.rec.fromrecords
_:
_v = df.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', '<U1'), ('A', '<i8'), ('B', '<i8')])
_
En ce qui concerne les performances, c'est presque la même chose (en fait, utiliser _rec.fromrecords
_ est un peu plus rapide).
_df2 = pd.concat([df] * 10000)
%timeit df2.to_records()
%%timeit
v = df2.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
11.1 ms ± 557 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
9.67 ms ± 126 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
_
to_numpy()
(en plus de array
) a été ajouté à la suite de discussions sous deux problèmes GitHub GH19954 et GH2362 .
Plus précisément, les docs mentionnent le raisonnement suivant:
[...] avec _
.values
_ il n'était pas clair si la valeur renvoyée serait le tableau réel, une transformation de celui-ci ou l'un des pandas tableaux personnalisés (commeCategorical
). Par exemple, avecPeriodIndex
, _.values
_ génère chaque fois un nouvel objetndarray
of period. [...]
_to_numpy
_ vise à améliorer la cohérence de l'API, ce qui constitue un pas important dans la bonne direction. _.values
_ ne sera pas obsolète dans la version actuelle, mais je suppose que cela pourrait se produire à l'avenir. J'invite donc les utilisateurs à migrer vers la nouvelle API dès que possible.
_DataFrame.values
_ a un comportement incohérent, comme déjà noté.
DataFrame.get_values()
est simplement un wrapper autour de _DataFrame.values
_, donc tout ce qui est dit ci-dessus s'applique.
DataFrame.as_matrix()
est obsolète maintenant, utilisez PAS!
Je voudrais juste enchaîner les fonctions DataFrame.reset_index () et DataFrame.values pour obtenir la représentation Numpy du cadre de données, y compris l'index:
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]])
Pour obtenir les types, nous aurions besoin de transformer ce ndarray en un tableau structuré en utilisant 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')])
Vous pouvez utiliser la méthode to_records
, mais vous devez jouer un peu avec les types de données s'ils ne correspondent pas à vos souhaits. Dans mon cas, après avoir copié votre DF à partir d'une chaîne, le type d'index est chaîne (représenté par un object
dtype dans les 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 conversion du type de recarray ne fonctionne pas pour moi, mais on peut déjà le faire dans Pandas déjà:
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')])
Notez que Pandas ne définit pas correctement le nom de l'index (sur ID
) dans le tableau d'enregistrements exporté (un bogue?), Nous profitons donc de la conversion de type pour corriger également cela.
Pour le moment, Pandas n'a que des entiers de 8 octets, i8
, et des flottants, f8
(voir this issue ).
Il semble que df.to_records()
fonctionnera pour vous. La fonctionnalité exacte que vous recherchez a été demandée et to_records
a été désignée comme alternative.
J'ai essayé cela localement en utilisant votre exemple, et cet appel produit quelque chose de très similaire au résultat que vous recherchiez:
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')])
Notez qu'il s'agit d'une recarray
plutôt que d'un array
. Vous pouvez déplacer le résultat dans un tableau numpy normal en appelant son constructeur sous la forme np.array(df.to_records())
.
Voici mon approche pour créer un tableau de structure à partir d'un pandas DataFrame.
Créer le bloc de données
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
Définissez la fonction pour créer un tableau de structure numpy (et non un tableau d’enregistrements) à partir d’un pandas DataFrame.
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
Utilisez reset_index
pour créer un nouveau cadre de données incluant l’index dans ses données. Convertissez ce cadre de données en un tableau de structure.
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')])
EDIT: Mise à jour de df_to_sarray pour éviter les erreurs lors de l’appel de .encode () avec python 3. Grâce à Joseph Garvin et halcyon pour leur commentaire et leur solution.
Deux façons de convertir le cadre de données en sa représentation Numpy-array.
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
Un moyen plus simple pour l'exemple DataFrame:
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
UTILISATION:
np.array(df.to_records().view(type=np.matrix))
OBTENIR:
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')]))
Vient juste d'avoir un problème similaire lors de l'exportation de dataframe vers la table arcgis et est tombé sur une solution de usgs ( https://my.usgs.gov/confluence/display/cdi/pandas.DataFrame+to++ArcGIS+Table ). En bref, votre problème a une solution similaire:
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
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
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')]))
Essaye ça:
a = numpy.asarray(df)
Suite à la réponse de meteore, j'ai trouvé le code
df.index = df.index.astype('i8')
ça ne marche pas pour moi. Donc, je mets mon code ici pour la commodité des autres coincés avec ce problème.
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))
Ecrivez to_numpy
au lieu de to_numpy()
pour conserver les types.
J'ai parcouru les réponses ci-dessus. La méthode "as_matrix ()" fonctionne mais est maintenant obsolète. Pour moi, ce qui a fonctionné était ". To_numpy ()".
Cela retourne un tableau multidimensionnel. Je préférerais utiliser cette méthode si vous lisez des données à partir d'une feuille Excel et que vous devez accéder à des données à partir d'un index. J'espère que cela t'aides :)