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?
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]])
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]])
values
und as_matrix()
nicht mehr!Ab v0.24.0 werden zwei brandneue, bevorzugte Methoden zum Abrufen von NumPy-Arrays aus pandas Objekten vorgestellt:
to_numpy()
, das für die Objekte Index
, _Series,
_ und DataFrame
definiert ist, undarray
, 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 .
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)
_
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 (wieCategorical
) sein würde. BeiPeriodIndex
generiert _.values
_ beispielsweise jedes Mal eine neuendarray
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.
_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!
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')])
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 ).
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.
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.
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
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')]))
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')]))
Versuche dies:
a = numpy.asarray(df)
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))
Schreiben Sie to_numpy
anstelle von to_numpy()
, um die d-Typen beizubehalten.
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 :)