将矩阵与列向量进行比较
Compare a matrix against a column vector
下面的数组 'A' 和向量 'B' 是 pandas 数据帧的一部分。
我有一个大数组 A
的形式:
28 39 52
77 80 66
7 18 24
9 97 68
我有一个向量 B
的形式:
32
5
42
17
如何通过 Python 方式比较 A 和 B 的每一列。我正在尝试获取 A < B 比较的 True/False 值以获得以下结果:
TRUE FALSE FALSE
FALSE FALSE FALSE
TRUE TRUE TRUE
TRUE FALSE FALSE
我可以做列表理解语法,但有没有更好的方法来实现它。我的数组 A 和 B 非常大。
更有效的方法是降低 numpy 级别(这里的 A、B 是数据帧):
A.values<B.values
您可以使用 lt
并在 B
上调用 squeeze
来执行此操作,以便将 df 展平为一维系列:
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
,它将尝试对齐我们不需要的列标签。我们想沿列轴广播比较结果
考虑 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
的解决方案速度更快,但不是那么快。它们的比例都相同。
另一个使用 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
转换为二维数组,以便 numpy 可以在比较两个不同形状的数组时进行广播。
下面的数组 'A' 和向量 'B' 是 pandas 数据帧的一部分。
我有一个大数组 A
的形式:
28 39 52
77 80 66
7 18 24
9 97 68
我有一个向量 B
的形式:
32
5
42
17
如何通过 Python 方式比较 A 和 B 的每一列。我正在尝试获取 A < B 比较的 True/False 值以获得以下结果:
TRUE FALSE FALSE
FALSE FALSE FALSE
TRUE TRUE TRUE
TRUE FALSE FALSE
我可以做列表理解语法,但有没有更好的方法来实现它。我的数组 A 和 B 非常大。
更有效的方法是降低 numpy 级别(这里的 A、B 是数据帧):
A.values<B.values
您可以使用 lt
并在 B
上调用 squeeze
来执行此操作,以便将 df 展平为一维系列:
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
,它将尝试对齐我们不需要的列标签。我们想沿列轴广播比较结果
考虑 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
的解决方案速度更快,但不是那么快。它们的比例都相同。
另一个使用 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
转换为二维数组,以便 numpy 可以在比较两个不同形状的数组时进行广播。