考虑pd.DataFrame
and pd.Series
, A
andB
A = pd.DataFrame([
[28, 39, 52],
[77, 80, 66],
[7, 18, 24],
[9, 97, 68]
])
B = pd.Series([32, 5, 42, 17])
pandas
默认情况下,当您将 apd.DataFrame
与 a进行比较时pd.Series
,pandas 会将系列中的每个索引值与数据框的列名对齐。这就是您使用A < B
. 在这种情况下,您的数据框中有 4 行,系列中有 4 个元素,因此我将假设您希望将系列的索引值与数据框的索引值对齐。为了指定要对齐的轴,您需要使用比较方法而不是运算符。那是因为当你使用方法时,你可以使用axis
参数并指定你想要axis=0
的而不是默认的axis=1
。
A.lt(B, axis=0)
0 1 2
0 True False False
1 False False False
2 True True True
3 True False False
我经常把它写成A.lt(B, 0)
numpy
在 numpy 中,您还必须注意数组的维数,并且假设位置已经排列好。如果它们来自同一数据框,则将处理这些位置。
print(A.values)
[[28 39 52]
[77 80 66]
[ 7 18 24]
[ 9 97 68]]
print(B.values)
[32 5 42 17]
请注意,这B
是一个一维数组,而 A 是一个二维数组。为了B
沿行进行比较,A
我们需要重塑B
为二维数组。最明显的方法是使用reshape
print(A.values < B.values.reshape(4, 1))
[[ True False False]
[False False False]
[ True True True]
[ True False False]]
但是,这些是您通常会看到其他人进行相同重塑的方式
A.values < B.values.reshape(-1, 1)
或者
A.values < B.values[:, None]
定时回测
为了掌握这些比较的速度有多快,我构建了以下回溯测试。
def pd_cmp(df, s):
return df.lt(s, 0)
def np_cmp_a2a(df, s):
"""To get an apples to apples comparison
I return the same thing in both functions"""
return pd.DataFrame(
df.values < s.values[:, None],
df.index, df.columns
)
def np_cmp_a2o(df, s):
"""To get an apples to oranges comparison
I return a numpy array"""
return df.values < s.values[:, None]
results = pd.DataFrame(
index=pd.Index([10, 1000, 100000], name='group size'),
columns=pd.Index(['pd_cmp', 'np_cmp_a2a', 'np_cmp_a2o'], name='method'),
)
from timeit import timeit
for i in results.index:
df = pd.concat([A] * i, ignore_index=True)
s = pd.concat([B] * i, ignore_index=True)
for j in results.columns:
results.set_value(
i, j,
timeit(
'{}(df, s)'.format(j),
'from __main__ import {}, df, s'.format(j),
number=100
)
)
results.plot()

我可以得出结论,numpy
基于解决方案的速度更快,但并不是那么快。它们的比例都相同。