我有兴趣知道如何将熊猫数据帧转换为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是的,这是真的,除了对我有用,我不知道为什么
它将返回,仅此而已。