Converteer panda’s-dataframe naar NumPy-array

Ik wil graag weten hoe ik een panda-dataframe kan converteren naar een NumPy-array.

dataframe:

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

geeft

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

Ik wil dit graag converteren naar een NumPy-array, als volgt:

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

Hoe kan ik dit doen?


Als een bonus, is het mogelijk om de dtypes op deze manier te behouden?

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

of vergelijkbaar?


Antwoord 1, autoriteit 100%

Gebruik deze code om een panda-dataframe (df) naar een numpy ndarray te converteren:

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

2, Autoriteit 99%

df.to_numpy()is beter dan df.values, hier is waarom. *

Het is tijd om uw gebruik van valuesen as_matrix().

te verwijderen

Panda’s v0.24.0Introducties twee nieuwe methoden voor het verkrijgen van numpy arrays van Panda’s Objects:

  1. to_numpy(), die is gedefinieerd op Index, Series, EN DataFrameObjecten en
  2. array, die is gedefinieerd met Indexen SeriesObjecten alleen.

Als u de V0.24-documenten bezoekt voor .values, u ziet een grote rode waarschuwing die zegt:

WAARSCHUWING: we raden u aan DataFrame.to_numpy()in plaats daarvan te gebruiken.

Zie Dit gedeelte van de V0.24.0-release-opmerkingen , en dit antwoord voor meer informatie.

* – to_numpy()is mijn aanbevolen methode voor elke productiecode die betrouwbaar moet worden uitgevoerd voor vele versies in de toekomst. Als u echter gewoon een ScratchPad in Jupyter of de Terminal maakt, is het gebruik van .valuesom een ​​paar milliseconden van typen op te slaan, een toegestane uitzondering. U kunt de fit n altijd later toevoegen.



Naar een betere consistentie: to_numpy()

In de geest van een betere consistentie in de hele API, is een nieuwe methode to_numpygeïntroduceerd om de onderliggende NumPy-array uit DataFrames te extraheren.

# Setup
df = pd.DataFrame(data={'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}, 
                  index=['a', 'b', 'c'])
# Convert the entire DataFrame
df.to_numpy()
# array([[1, 4, 7],
#        [2, 5, 8],
#        [3, 6, 9]])
# Convert specific columns
df[['A', 'C']].to_numpy()
# array([[1, 7],
#        [2, 8],
#        [3, 9]])

Zoals hierboven vermeld, is deze methode ook gedefinieerd voor Index– en Series-objecten (zie hier).

df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
#  array([1, 2, 3])

Standaard wordt een weergave geretourneerd, dus eventuele wijzigingen hebben invloed op het origineel.

v = df.to_numpy()
v[0, 0] = -1
df
   A  B  C
a -1  4  7
b  2  5  8
c  3  6  9

Als je in plaats daarvan een kopie nodig hebt, gebruik dan to_numpy(copy=True).


panda’s >= 1.0 update voor ExtensionTypes

Als je panda’s 1.x gebruikt, is de kans groot dat je veel meer met extensietypen te maken krijgt. Je moet wat voorzichtiger zijn dat deze extensietypes correct worden geconverteerd.

a = pd.array([1, 2, None], dtype="Int64")                                  
a                                                                          
<IntegerArray>
[1, 2, <NA>]
Length: 3, dtype: Int64 
# Wrong
a.to_numpy()                                                               
# array([1, 2, <NA>], dtype=object)  # yuck, objects
# Correct
a.to_numpy(dtype='float', na_value=np.nan)                                 
# array([ 1.,  2., nan])
# Also correct
a.to_numpy(dtype='int', na_value=-1)
# array([ 1,  2, -1])

Dit is geroepen in de documenten.


Als je de dtypesnodig hebt in het resultaat…

Zoals blijkt uit een ander antwoord, DataFrame.to_recordsis een goede manier om dit te doen.

df.to_records()
# rec.array([('a', 1, 4, 7), ('b', 2, 5, 8), ('c', 3, 6, 9)],
#           dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8'), ('C', '<i8')])

Dit kan helaas niet met to_numpy. Als alternatief kunt u echter np.rec.fromrecordsgebruiken:

v = df.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
# rec.array([('a', 1, 4, 7), ('b', 2, 5, 8), ('c', 3, 6, 9)],
#           dtype=[('index', '<U1'), ('A', '<i8'), ('B', '<i8'), ('C', '<i8')])

Performance Wise, het is bijna hetzelfde (eigenlijk, met rec.fromrecordsis een beetje sneller).

df2 = pd.concat([df] * 10000)
%timeit df2.to_records()
%%timeit
v = df2.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
12.9 ms ± 511 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
9.56 ms ± 291 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


Rationale voor het toevoegen van een nieuwe methode

to_numpy()(in aanvulling op array) is toegevoegd als gevolg van discussies onder twee GitHub-problemen GH19954 en GH23623 .

Specifiek vermelden de DOCS de reden:

[…] met .valueshet was onduidelijk of de geretourneerde waarde de
Werkelijke array, enige transformatie ervan, of een van Pandas Custom
Arrays (zoals Categorical). Bijvoorbeeld, met PeriodIndex, .values
Genereert elke keer een nieuwe ndarrayvan periodeobjecten. […]

to_numpyis bedoeld om de consistentie van de API te verbeteren, wat een belangrijke stap in de goede richting is. .valuesWORDT NIET VERDELD IN DE HUIDIGE VERSIE, maar ik verwacht dat dit op een bepaald moment in de toekomst kan gebeuren, dus ik zou u willen dringen om zo snel mogelijk naar de nieuwere API te migreren naar de nieuwere API.



kritiek op andere oplossingen

DataFrame.valuesheeft inconsistent gedrag, zoals reeds opgemerkt.

DataFrame.get_values()is gewoon een wikkel rond DataFrame.values, dus alles wat hierboven is gezegd, is van toepassing.

DataFrame.as_matrix()wordt nu verouderd, doe niet Gebruik!


3, Autoriteit 29%

OPMERKING : de .as_matrix()methode die in dit antwoord wordt gebruikt, wordt verouderd. Panda’s 0.23.4 waarschuwt:

METHODE .as_matrixwordt in een toekomstige versie verwijderd. Gebruik in plaats daarvan.


Panda’s heeft iets ingebouwd in …

numpy_matrix = df.as_matrix()

geeft

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

4, Autoriteit 17%

Ik zou gewoon de dataframe.reset_index () en Dataframe.Values ​​functioneert om de numpy-weergave van het dataframe te krijgen, inclusief De 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]])

Om de dtypes te krijgen, moeten we deze ndarray transformeren in een gestructureerde array met behulp van bekijken:

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

5, Autoriteit 6%

Het lijkt als df.to_records()zal voor u werken. De exacte functie U bent op zoek naar werd gevraagd en to_recordswees naar als alternatief.

Ik heb dit lokaal geprobeerd met behulp van uw voorbeeld, en die oproep levert iets op dezelfde manier op de uitvoer die u zoekt:

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

Merk op dat dit een recarrayis in plaats van een array. U kunt het resultaat naar een gewone numpy-array verplaatsen door de constructor ervan aan te roepen als np.array(df.to_records()).


Antwoord 6, autoriteit 4%

Probeer dit:

a = numpy.asarray(df)

Antwoord 7, autoriteit 2%

Hier is mijn benadering voor het maken van een structuurarray van een panda’s DataFrame.

Maak het dataframe

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

Definieer functie om een numpy structure array (geen record array) te maken van een panda’s 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

Gebruik reset_indexom een nieuw gegevensframe te maken dat de index als onderdeel van de gegevens bevat. Converteer dat dataframe naar een structuurarray.

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: df_to_sarray bijgewerkt om fouten bij het bellen van .encode() met python 3 te voorkomen. Met dank aan Joseph Garvinen halcyonvoor hun commentaar en oplossing.


Antwoord 8, autoriteit 2%

Een eenvoudigere manier voor een voorbeelddataframe:

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

GEBRUIK:

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

KRIJG:

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

9, Autoriteit 2%

Twee manieren om het gegevensframe om te zetten naar de numpy-array-weergave.

  • mah_np_array = df.as_matrix(columns=None)

  • mah_np_array = df.values

DOC: HTTPS: //PANDAS.PYDATA. Org / Panda’s-Docs / Stable / Gegenereerd / Pandas.Dataframe.as_Matrix.html


10

Had gewoon een soortgelijk probleem bij het exporteren van Dataframe naar Arcgis Table en struikelde op een oplossing van USGS (https://my.USGS.gov/confluence/display/cdi/pandas.dataframe+to+arcgis+table ).
Kortom uw probleem heeft een vergelijkbare oplossing:

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

11

Probeer dit:

np.array(df) 
array([['ID', nan, nan, nan],
   ['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=object)

Nog enkele informatie op: [https: // docs .cipy.org / doc / numpy / referentie / gegenereerd / numpy.array.html]
Geldig voor numpy 1.16.5 en panda’s 0.25.2.


12

Verder naar het antwoord van Meteore, vond ik de code

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

werkt niet voor mij. Dus ik heb mijn code hier voor het gemak van anderen geplakt bij dit probleem.

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

13

Een eenvoudige manier om dataframe naar Numpy Array te converteren:

import pandas as pd
df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
df_to_array = df.to_numpy()
array([[1, 3],
   [2, 4]])

Gebruik van to_numpy wordt aangemoedigd om de consistentie te behouden.

Referentie:
https://pandas.pydata.org/ Panda’s-Docs / Stable / Reference / API / Pandas.Dataframe.to_numpy.html

Other episodes