簡體   English   中英

將 pandas dataframe 轉換為 Z3B7F949B2343F9E5390​​E29F6EF5E1778Z 數組

[英]Convert pandas dataframe to NumPy array

如何將 pandas dataframe 轉換為 Z3B7F949B2343F9E5390​​E29F6EF5E1778Z 數組?

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

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

我想將其轉換為 Z3B7F949B2343F9E5390​​E29F6EF5E1778Z 數組,如下所示:

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

另外,是否可以像這樣保留數據類型?

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

df.to_numpy()df.values好,這就是原因。 *

是時候棄用valuesas_matrix()了。

pandas v0.24.0引入了兩種從 pandas 對象獲取 NumPy 數組的新方法:

  1. to_numpy() ,在IndexSeriesDataFrame對象上定義,以及
  2. array ,僅在IndexSeries對象上定義。

如果您訪問 .values 的.values文檔,您會看到一個大紅色警告,上面寫着:

警告:我們建議改用DataFrame.to_numpy()

請參閱v0.24.0 發行說明的這一部分,以及此答案以獲取更多信息。

* - to_numpy()是我推薦的任何生產代碼的方法,這些生產代碼需要在未來的許多版本中可靠運行。 但是,如果您只是在 jupyter 或終端中制作暫存器,則使用.values來節省幾毫秒的輸入時間是一個允許的例外。 您可以隨時添加適合 n 完成以后。



實現更好的一致性: to_numpy()

本着在整個 API 中保持更好一致性的精神,引入了一種新方法to_numpy來從 DataFrames 中提取底層 NumPy 數組。

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

如上所述,此方法也在IndexSeries對象上定義(參見此處)。

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

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

默認情況下,會返回一個視圖,因此所做的任何修改都會影響原始視圖。

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

如果您需要副本,請使用to_numpy(copy=True)


擴展類型的熊貓 >= 1.0 更新

如果您使用的是 pandas 1.x,那么您可能會更多地處理擴展類型。 您必須更加小心這些擴展類型是否正確轉換。

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

在 docs 中被提及


如果您需要結果中的dtypes ...

如另一個答案所示, DataFrame.to_records是一種很好的方法。

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

不幸的是,這不能用to_numpy完成。 但是,作為替代方案,您可以使用np.rec.fromrecords

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

性能方面,幾乎相同(實際上,使用rec.fromrecords會快一點)。

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)


添加新方法的理由

由於在兩個 GitHub 問題GH19954GH23623下的討論,添加了to_numpy() (除了array )。

具體來說,文檔提到了理由:

[...] .values不清楚返回的值是實際數組、它的一些轉換,還是熊貓自定義數組之一(如Categorical )。 例如,使用PeriodIndex.values生成一個新的周期對象ndarray [...]

to_numpy旨在提高 API 的一致性,這是朝着正確方向邁出的重要一步。 .values在當前版本中不會被棄用,但我預計這可能會在未來的某個時候發生,所以我會敦促用戶盡快遷移到更新的 API。



對其他解決方案的批評

如前所述, DataFrame.values的行為不一致。

DataFrame.get_values()只是DataFrame.values的一個包裝器,所以上面所說的一切都適用。

DataFrame.as_matrix()現在已棄用,請勿使用!

要將 pandas 數據幀 (df) 轉換為 numpy ndarray,請使用以下代碼:

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

注意:此答案中使用的.as_matrix()方法已棄用。 熊貓 0.23.4 警告:

方法.as_matrix將在未來版本中刪除。 請改用 .values。


Pandas 內置了一些東西...

numpy_matrix = df.as_matrix()

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

我將鏈接DataFrame.reset_index()DataFrame.values函數來獲取數據幀的 Numpy 表示,包括索引:

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

要獲得 dtypes,我們需要使用view將此 ndarray 轉換為結構化數組:

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

您可以使用to_records方法,但如果它們不是您從一開始就想要的,則必須使用 dtypes。 在我的例子中,從字符串中復制了你的 DF,索引類型是字符串(由 pandas 中的object dtype 表示):

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

轉換 recarray dtype 對我不起作用,但已經可以在 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')])

請注意,Pandas 沒有在導出的記錄數組中正確設置索引的名稱(到ID )(一個錯誤?),所以我們從類型轉換中受益,也糾正了這一點。

目前,Pandas 只有 8 字節整數i8和浮點數f8 (請參閱本期)。

似乎df.to_records()會為您工作。 您正在尋找的確切功能已被請求,並且to_records指出作為替代。

我使用您的示例在本地進行了嘗試,該調用產生的輸出與您正在尋找的輸出非常相似:

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

請注意,這是一個recarray而不是array 您可以通過將其構造函數調用為np.array(df.to_records())將結果移動到常規 numpy 數組中。

嘗試這個:

a = numpy.asarray(df)

這是我從 pandas 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

定義函數以從 pandas DataFrame 創建一個 numpy 結構數組(不是記錄數組)。

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

使用reset_index創建一個新的數據框,其中包含索引作為其數據的一部分。 將該數據框轉換為結構體數組。

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

編輯:更新 df_to_sarray 以避免使用 python 3 調用 .encode() 時出錯。感謝Joseph Garvinhalcyon的評論和解決方案。

示例 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

利用:

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

得到:

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

將數據幀轉換為其 Numpy 數組表示的兩種方法。

  • mah_np_array = df.as_matrix(columns=None)

  • mah_np_array = df.values

文檔: https ://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.as_matrix.html

我瀏覽了上面的答案。 as_matrix() ” 方法有效,但現在已過時。 對我來說,有效的是“ .to_numpy() ”。

這將返回一個多維數組。 如果您從 excel 表中讀取數據並且需要從任何索引訪問數據,我會更喜歡使用此方法。 希望這可以幫助 :)

從數據框導出到 arcgis 表時遇到了類似的問題,偶然發現了 usgs 的解決方案( https://my.usgs.gov/confluence/display/cdi/pandas.DataFrame+to+ArcGIS+Table )。 簡而言之,您的問題有類似的解決方案:

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

將數據幀轉換為 numpy 數組的簡單方法:

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

鼓勵使用 to_numpy 以保持一致性。

參考: https ://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_numpy.html

嘗試這個:

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)

更多信息位於:[ https://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html]適用於 numpy 1.16.5 和 pandas 0.25.2。

除了流星的回答,我找到了代碼

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

對我不起作用。 所以我把我的代碼放在這里是為了方便其他人遇到這個問題。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM