python把dataframe变成array_关于python:将pandas dataframe转换为NumPy数组

我有兴趣知道如何将熊猫数据帧转换为numpy数组。

数据文件:

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

我想将其转换为numpy数组,如下所示:

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

或类似的。

关于如何实现这一点有什么建议吗?

你为什么需要这个?数据帧不是基于numpy数组吗?您应该能够在需要numpy数组的地方使用数据帧。这就是为什么可以将数据帧与SciKit一起使用的原因,了解函数在哪里要求numpy数组。

以下是有关dtypes&recarray(又称记录数组或结构化数组)的几个可能相关链接:(1)stackoverflow.com/questions/9949427/…(2)stackoverflow.com/questions/52579601/…

从v0.24开始,.values将不再是访问底层numpy数组的首选方法。看看这个答案。

同样相关:如何将pandas列或索引转换为numpy数组?

要将熊猫数据帧(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]])

这不起作用,数据类型仍然被删除(您会丢失名称)。

这并不能回答问题。

关于数据类型-你不能在以后只做df.astype(__yourtype__)吗?

@约瑟夫加文,我增加了一个答案。更重要的是,从v0.24起不再使用.values。我已经解释了原因。

注:此答案中使用的.as_matrix()方法已被弃用。熊猫0.23.4警告:

Method .as_matrix will be removed in a future version. Use .values instead.

熊猫有内在的东西…

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

这不会给出结构化数组,所有列都是object类型的数据。

"0.23.0版之后已弃用:请改用dataframe.values。"/"此方法是为了向后兼容而提供的。"通常,建议使用".values"。-github.com/pandas dev/pandas/blob/…

现在已弃用。从v0.24开始,请使用to_numpy代替(也不是.values)。这里更多。

"FutureWarning:方法。因为在将来的版本中将删除矩阵。"改为使用.values。"

我只需要链接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]])

要获取数据类型,我们需要使用视图将此数据数组转换为结构化数组:

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

这个答案中唯一缺少的就是如何从数据帧构造数据类型,以便您可以编写一个泛型函数。

反对你使用values和as_matrix()!

从v0.24.0开始,我们介绍了从熊猫对象获取numpy数组的两种全新的首选方法:

在Index、Series,和DataFrame对象上定义的to_numpy(),以及

array,仅在Index和Series对象上定义。

如果您访问.values的v0.24文档,您将看到一个红色的大警告:

Warning: We recommend using DataFrame.to_numpy() instead.

有关更多信息,请参阅v0.24.0发行说明的这一部分和此答案。为了更好的一致性:to_numpy()。

为了在整个API中保持更好的一致性,引入了一种新的方法to_numpy,从数据帧中提取底层numpy数组。

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

如上所述,此方法也在Index和Series对象上定义(请参见此处)。

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

a -1  4

b  2  5

c  3  6

如果您需要副本,请使用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

如果你需要保存dtypes…如另一个答案所示,DataFrame.to_records是一个很好的方法。

df.to_records()

# rec.array([('a', -1, 4), ('b',  2, 5), ('c',  3, 6)],

#           dtype=[('index', 'O'), ('A', '

不幸的是,这不能用to_numpy来完成。但是,作为替代方案,您可以使用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', '

从性能上讲,它几乎是相同的(实际上,使用rec.fromrecords要快一点)。

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)

添加新方法的理由

由于在两个Github问题GH19954和GH23623下的讨论,增加了to_numpy()(除array)。

具体来说,文件提到了理由:

[...] with .values it was unclear whether the returned value would be the

actual array, some transformation of it, or one of pandas custom

arrays (like Categorical). For example, with PeriodIndex, .values

generates a new ndarray of period objects each time. [...]

to_numpy旨在提高API的一致性,这是朝着正确方向迈出的重要一步。.values在当前版本中不会被弃用,但我预计将来某个时候可能会发生这种情况,因此我会敦促用户尽快迁移到新的API。对其他解决方案的批评

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

DataFrame.get_values()只是DataFrame.values的包装,所以上面所说的一切都适用。

现在不推荐使用DataFrame.as_matrix(),不要使用!

你可以使用to_records方法,但是如果数据类型不是你想要的,就必须对它们进行一些处理。在我的例子中,从字符串中复制了df之后,索引类型是string(用pandas中的objectdtype表示):

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

In [106]: df.to_records().dtype

Out[106]: dtype([('index', '|O8'), ('A', '

转换recarray数据类型对我来说不起作用,但在pandas中可以这样做:

In [109]: df.index = df.index.astype('i8')

In [111]: df.to_records().view([('ID', '

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

注意,pandas没有在导出的记录数组(bug?)中正确设置索引的名称(到ID)。因此,我们从类型转换中获益,并对此进行了修正。

目前,pandas只有8字节的整数i8和float,f8(见本期)。

要获得备受追捧的结构化数组(它的性能比recarray好),只需将recarray传递给np.array构造函数。

索引名称错误:github.com/pydata/pandas/issues/2161

我们只是对上面显示的索引名进行了设置。

似乎江户十一〔九〕会为你工作。您要查找的确切功能已被请求,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', '

注意,这是一个recarray,而不是一个array。您可以通过将其构造函数调用为np.array(df.to_records()),将结果移到常规numpy数组中。

等等,这个答案与@meatele五年前提到过to_records()的另一个答案相比又增加了什么?

下面是我从熊猫数据帧制作结构数组的方法。

创建数据帧

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

定义函数,从熊猫数据帧生成一个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', '

编辑:将df_更新为u sarray以避免使用python 3调用.encode()时出错。感谢Joseph Garvin和Halcyon的评论和解决方案。

对我无效,错误:类型错误:数据类型不理解

感谢您的评论,并感谢Halcyon的更正。我更新了我的答案,希望它现在对你有用。

一种简单的方法,例如数据帧:

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

('reg', '

将数据帧转换为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

刚从数据帧导出到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', '

关于Meteore的答案,我找到了密码

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

写to_numpy而不是to_numpy()来保存数据类型。

to_numpy实际上并不调用函数。这是错误的。

@Coldspeed是的,这是真的,除了对我有用,我不知道为什么

它将返回,仅此而已。

你可能感兴趣的:(python把dataframe变成array_关于python:将pandas dataframe转换为NumPy数组)