it-swarm.com.de

Konvertiert pandas Datenrahmen in ein NumPy-Array

Ich möchte wissen, wie ein pandas -Datenrahmen in ein NumPy-Array konvertiert wird.

datenrahmen:

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

gibt

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

Ich möchte dies wie folgt in ein NumPy-Array konvertieren:

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

Wie kann ich das machen?


Ist es als Bonus möglich, die D-Typen wie folgt zu erhalten?

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

oder ähnliches?

349

Verwenden Sie diesen Code, um einen pandas -Datenrahmen (df) in einen numpy ndarray zu konvertieren:

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]])
308
User456898

Hinweis : Die in dieser Antwort verwendete Methode .as_matrix() ist veraltet. Pandas 0.23.4 warnt:

Methode .as_matrix wird in einer zukünftigen Version entfernt. Verwenden Sie stattdessen .values.


Pandas hat etwas eingebaut ...

numpy_matrix = df.as_matrix()

gibt

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]])
125
ZJS

Verwenden Sie values und as_matrix() nicht mehr!

Ab v0.24.0 werden zwei brandneue, bevorzugte Methoden zum Abrufen von NumPy-Arrays aus pandas Objekten vorgestellt:

  1. to_numpy(), das für die Objekte Index, _Series,_ und DataFrame definiert ist, und
  2. array, das nur für Index- und Series-Objekte definiert wird.

Wenn Sie die v0.24-Dokumentation für .values besuchen, wird eine große rote Warnung angezeigt, die besagt:

Warnung: Wir empfehlen, stattdessen DataFrame.to_numpy() zu verwenden.

Weitere Informationen finden Sie in dieser Abschnitt der Versionshinweise zu Version 0.24. und diese Antwort .


Auf dem Weg zu einer besseren Konsistenz: to_numpy()

Im Sinne einer besseren Konsistenz in der gesamten API wurde eine neue Methode _to_numpy_ eingeführt, um das zugrunde liegende NumPy-Array aus DataFrames zu extrahieren.

_# 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]])
_

Wie oben erwähnt, ist diese Methode auch für Index- und Series-Objekte definiert (siehe hier ).

_df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)

df['A'].to_numpy()
#  array([1, 2, 3])
_

Standardmäßig wird eine Ansicht zurückgegeben, sodass sich alle vorgenommenen Änderungen auf das Original auswirken.

_v = df.to_numpy()
v[0, 0] = -1

df
   A  B
a -1  4
b  2  5
c  3  6
_

Wenn Sie stattdessen eine Kopie benötigen, verwenden Sie _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
_

Wenn Sie die dtypes... bewahren müssen
Wie in einer anderen Antwort gezeigt, ist DataFrame.to_records ein guter Weg, dies zu tun.

_df.to_records()
# rec.array([('a', -1, 4), ('b',  2, 5), ('c',  3, 6)],
#           dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])
_

Dies ist mit _to_numpy_ leider nicht möglich. Alternativ können Sie jedoch _np.rec.fromrecords_ verwenden:

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

Leistungstechnisch ist es fast dasselbe (tatsächlich ist die Verwendung von _rec.fromrecords_ etwas schneller).

_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)
_

Gründe für das Hinzufügen einer neuen Methode

to_numpy() (zusätzlich zu array) wurde als Ergebnis von Diskussionen zu zwei GitHub-Problemen hinzugefügt GH19954 und GH2362 .

Insbesondere erwähnen die Dokumente die Begründung:

[...] mit _.values_ war unklar, ob der zurückgegebene Wert das tatsächliche Array, eine Transformation davon oder eines von pandas benutzerdefinierten Arrays (wie Categorical) sein würde. Bei PeriodIndex generiert _.values_ beispielsweise jedes Mal eine neue ndarray von Periodenobjekten. [...]

_to_numpy_ soll die Konsistenz der API verbessern, was ein wichtiger Schritt in die richtige Richtung ist. _.values_ wird in der aktuellen Version nicht mehr unterstützt. Ich gehe jedoch davon aus, dass dies irgendwann in der Zukunft der Fall sein wird, und fordere die Benutzer daher dringend auf, so bald wie möglich auf die neuere API umzusteigen.


Kritik anderer Lösungen

_DataFrame.values_ weist, wie bereits erwähnt, ein inkonsistentes Verhalten auf.

DataFrame.get_values() ist einfach ein Wrapper um _DataFrame.values_, daher gilt alles oben Gesagte.

DataFrame.as_matrix() ist jetzt veraltet, benutze NICHT!

105
cs95

Ich würde einfach die Funktionen DataFrame.reset_index () und DataFrame.values verketten, um die Numpy-Darstellung des Datenrahmens einschließlich des Index zu erhalten:

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

Um die dtypes zu erhalten, müssten wir dieses ndarray mit view in ein strukturiertes Array umwandeln:

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

Sie können die to_records -Methode verwenden, müssen aber ein bisschen mit den dtypes herumspielen, wenn sie von Anfang an nicht Ihren Wünschen entsprechen. In meinem Fall, nachdem Sie DF aus einer Zeichenfolge kopiert haben, lautet der Indextyp string (in Pandas durch object dtype dargestellt):

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

Das Konvertieren des Recarray-D-Typs funktioniert bei mir nicht, aber dies kann man bereits in Pandas tun:

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

Beachten Sie, dass Pandas den Namen des Index im exportierten Datensatzarray nicht richtig (auf ID) setzt (ein Fehler?), Sodass wir von der Typkonvertierung profitieren, um dies ebenfalls zu korrigieren.

Im Moment hat Pandas nur 8-Byte-Ganzzahlen, i8, und schwebt, f8 (siehe dies Ausgabe ).

31
meteore

Es scheint, als würde df.to_records() für Sie funktionieren. Die genaue Funktion, nach der Sie suchen wurde angefordert und to_records als Alternative.

Ich habe dies lokal anhand Ihres Beispiels ausprobiert und dieser Aufruf ergibt etwas, das der gesuchten Ausgabe sehr ähnlich ist:

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

Beachten Sie, dass dies ein recarray und kein array ist. Sie können das Ergebnis in ein reguläres Numpy-Array verschieben, indem Sie dessen Konstruktor als np.array(df.to_records()) aufrufen.

22
Jamie Doyle

Hier ist mein Ansatz zum Erstellen eines Strukturarrays aus einem pandas -Datenrahmen.

Erstellen Sie den Datenrahmen

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

Definieren Sie eine Funktion, um aus einem pandas -Datenrahmen ein Numpy-Strukturarray (kein Datensatzarray) zu erstellen.

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

Verwenden Sie reset_index, um einen neuen Datenrahmen zu erstellen, der den Index als Teil seiner Daten enthält. Konvertieren Sie diesen Datenrahmen in ein Strukturarray.

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

BEARBEITEN: df_to_sarray aktualisiert, um Fehler beim Aufrufen von .encode () mit python zu vermeiden. 3. Dank an Joseph Garvin und halcyon für den Kommentar und die Lösung.

8
Phil

Zwei Möglichkeiten, den Datenrahmen in seine Numpy-Array-Darstellung zu konvertieren.

  • 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

6

Ein einfacher Weg zum Beispiel für 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

VERWENDEN:

np.array(df.to_records().view(type=np.matrix))

BEKOMMEN:

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')]))
4
Yanni Papadakis

Hatte gerade ein ähnliches Problem beim Exportieren von Datenrahmen in eine ArcGIS-Tabelle und stieß auf eine Lösung von usgs ( https://my.usgs.gov/confluence/display/cdi/pandas.DataFrame+to+ArcGIS+Table ). Kurz gesagt, Ihr Problem hat eine ähnliche Lösung:

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

Versuche dies:

a = numpy.asarray(df)
4
Dadu Khan

Neben der Antwort von meteore habe ich den Code gefunden

df.index = df.index.astype('i8')

funktioniert bei mir nicht Deshalb habe ich meinen Code hier eingefügt, damit andere sich mit diesem Problem befassen.

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))
2
James L

Schreiben Sie to_numpy anstelle von to_numpy(), um die d-Typen beizubehalten.

1
Shuang Li

Ich habe die Antworten oben durchgesehen. Die Methode "as_matrix ()" funktioniert, ist jetzt aber veraltet. Für mich hat ". To_numpy ()" funktioniert.

Dies gibt ein mehrdimensionales Array zurück. Ich bevorzuge diese Methode, wenn Sie Daten aus einer Excel-Tabelle lesen und auf Daten aus einem beliebigen Index zugreifen müssen. Hoffe das hilft :)

0
Arsam