使用 df.to_numpy()
它比df.values
更好,原因如下。*
现在是时候停止使用values
和as_matrix()
了。
pandas v0.24.0引入了两个新方法,用于从pandas对象中获取NumPy数组:
to_numpy()
,定义在Index
、Series
和DataFrame对象上;
array
,只在Index
和Series
对象上定义。
如果您访问.values
的v0.24文档,您将看到一个大大的红色警告,上面写着:
警告:我们建议使用DataFrame.to_numpy()
代替。
有关更多信息,请参见v0.24.0发布说明和此答案。
*- to_numpy()
是我推荐的方法,适用于任何需要可靠运行多个版本的生产代码。但是,如果您只是在jupyter或终端中制作一个草稿,使用.values
来节省几毫秒的打字时间是可以接受的例外情况。您随时可以稍后添加fit n finish。
为了更好地保持API的一致性,引入了一个新方法to_numpy
,用于从数据框中提取底层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]])
如上所述,这种方法还在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 C
a -1 4 7
b 2 5 8
c 3 6 9
如果你需要一份副本,可以使用to_numpy(copy=True)
。
pandas >= 1.0 更新 ExtensionTypes
如果你正在使用 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])
这在文档中被称为“整数数组现在使用Pandas NA”。
如果您需要结果中的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问题GH19954和GH23623的讨论下,除了array
之外,还添加了to_numpy()
。
具体来说,文档中提到了以下原因:
[...] 使用.values
时,返回值是否为实际数组、其某种转换或Pandas定制数组(如Categorical
)是不清楚的。例如,对于PeriodIndex
,每次使用.values
都会生成一个新的周期对象的ndarray
。[...]
to_numpy
旨在提高API的一致性,这是正确方向的重要一步。当前版本不会弃用.values
,但我预计在未来某个时候可能会发生这种情况,所以我建议用户尽快迁移到较新的API。
对其他解决方案的批评
DataFrame.values
的行为不一致,正如先前所述。
DataFrame.get_values()
在v1.0中被静默删除,之前在v0.25中被弃用。在此之前,它只是DataFrame.values
的一个包装器,因此上面所说的所有内容都适用。
DataFrame.as_matrix()
在v1.0中被删除,在v0.23中被弃用。 请勿使用!