下面的数组'A'和向量'B'是pandas数据帧的一部分。
我有一个大型数组A
:
28 39 52
77 80 66
7 18 24
9 97 68
我的格式为B
:
32
5
42
17
我如何py的比较A的每一列与B.我试图获得A<的真/假值。 B比较得到以下结果:
TRUE FALSE FALSE
FALSE FALSE FALSE
TRUE TRUE TRUE
TRUE FALSE FALSE
我可以做列表理解语法,但有更好的方法来解决这个问题。我的阵列A和B非常大。
答案 0 :(得分:14)
考虑pd.DataFrame
和pd.Series
,A
和B
A = pd.DataFrame([
[28, 39, 52],
[77, 80, 66],
[7, 18, 24],
[9, 97, 68]
])
B = pd.Series([32, 5, 42, 17])
pandas
默认情况下,当您将pd.DataFrame
与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
的解决方案速度更快,但并不是那么多。它们都是相同的。
答案 1 :(得分:3)
更高效的是降低numpy级别(A,B是DataFrames):
A.values<B.values
答案 2 :(得分:3)
您可以使用lt
并在squeeze
上调用B
来执行此操作,以便将df展平为1-D系列:
In [107]:
A.lt(B.squeeze(),axis=0)
Out[107]:
0 1 2
0 True False False
1 False False False
2 True True True
3 True False False
问题在于,如果没有squeeze
,它会尝试对齐我们不想要的列标签。我们想沿列轴广播比较
答案 3 :(得分:2)
使用numpy的另一个选项是使用numpy.newaxis
In [99]: B = B[:, np.newaxis]
In [100]: B
Out[100]:
array([[32],
[ 5],
[42],
[17]])
In [101]: A < B
Out[101]:
array([[ True, False, False],
[False, False, False],
[ True, True, True],
[ True, False, False]], dtype=bool)
基本上,我们将矢量B
转换为2D数组,以便在比较两个不同形状的数组时numpy可以广播。