根据列向量制作 Pandas 掩码
Make a Pandas mask based on a column vector
我有一个给定的数据框,我希望每一行都能够 select 高于该行给定百分位数的值。
让我们考虑这个数据框:
df = pd.DataFrame({'A' : [5,6,3,4, 0,5,9], 'B' : [1,2,3, 5,7,0,1]})
A B
0 5 1
1 6 2
2 3 3
3 4 5
4 0 7
5 5 0
6 9 1
每行第 20 个分位数的给定向量:
rowsQuantiles = df.quantile(0.2, axis=1)
0 1.8
1 2.8
2 3.0
3 4.2
4 1.4
5 1.0
6 2.6
我希望能够为每一行过滤掉低于该行分位数的值,以获得以下结果:
quantileMask = df > rowsQuantiles
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
编辑:
我真的很喜欢@andrew_reece 和@Andy Hayden 的两种方法,所以我决定看看哪一种是 fastet/best-implemented:
N=10000000
df = pd.DataFrame({'A' : [random.random() for i in range(N)], 'B' : [random.random() for i in range(N)]})
rowsQuantiles = df.quantile(0.2, axis=1)
t0=time.time()
mask=(df.T>rowsQuantiles).T
#mask=df.apply(lambda row: row > rowsQuantiles)
print(str(time.time()-t0))
结果非常简单(经过多次重复测试):
- 220 毫秒 对于
mask=(df.T>rowsQuantiles).T
- 65 毫秒 对于
mask=df.apply(lambda row: row > rowsQuantiles)
- 21ms for
df.gt(rowsQuantiles,0)
,已接受的答案。
你的掩码存在转置错误,但假设你想用 NaN 替换值,你正在寻找的方法是 where
:
In [11]: df.T > rowsQuantiles
Out[11]:
0 1 2 3 4 5 6
A True True False False False True True
B False False False True True False False
In [12]: (df.T > rowsQuantiles).T
Out[12]:
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
In [13]: df.where((df.T > rowsQuantiles).T)
Out[13]:
A B
0 5.0 NaN
1 6.0 NaN
2 NaN NaN
3 NaN 5.0
4 NaN 7.0
5 5.0 NaN
6 9.0 NaN
df.apply(lambda row: row > rowsQuantiles)
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
我可以支持的另一种选择是 np.where
:
np.where(df.values > rowsQuantiles[:, None], True, False)
array([[ True, False],
[ True, False],
[False, False],
[False, True],
[False, True],
[ True, False],
[ True, False]], dtype=bool)
哪个 returns 一个 numpy
数组,如果你同意的话。
时间
%timeit df.T > rowsQuantiles
1 loop, best of 3: 251 ms per loop
%timeit df.where((df.T > rowsQuantiles).T)
1 loop, best of 3: 583 ms per loop
%timeit np.where(df.values > rowsQuantiles[:, None], True, False)
10 loops, best of 3: 136 ms per loop
%timeit df.add(-rowsQuantiles,0).gt(0)
10 loops, best of 3: 141 ms per loop
%timeit df.gt(rowsQuantiles,0)
10 loops, best of 3: 25.4 ms per loop
%timeit df.apply(lambda row: row > rowsQuantiles)
10 loops, best of 3: 60.6 ms per loop
也只使用gt
df.gt(rowsQuantiles,0)
Out[288]:
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
使用add
df.add(-rowsQuantiles,0).gt(0)
Out[284]:
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
我有一个给定的数据框,我希望每一行都能够 select 高于该行给定百分位数的值。
让我们考虑这个数据框:
df = pd.DataFrame({'A' : [5,6,3,4, 0,5,9], 'B' : [1,2,3, 5,7,0,1]})
A B
0 5 1
1 6 2
2 3 3
3 4 5
4 0 7
5 5 0
6 9 1
每行第 20 个分位数的给定向量:
rowsQuantiles = df.quantile(0.2, axis=1)
0 1.8
1 2.8
2 3.0
3 4.2
4 1.4
5 1.0
6 2.6
我希望能够为每一行过滤掉低于该行分位数的值,以获得以下结果:
quantileMask = df > rowsQuantiles
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
编辑:
我真的很喜欢@andrew_reece 和@Andy Hayden 的两种方法,所以我决定看看哪一种是 fastet/best-implemented:
N=10000000
df = pd.DataFrame({'A' : [random.random() for i in range(N)], 'B' : [random.random() for i in range(N)]})
rowsQuantiles = df.quantile(0.2, axis=1)
t0=time.time()
mask=(df.T>rowsQuantiles).T
#mask=df.apply(lambda row: row > rowsQuantiles)
print(str(time.time()-t0))
结果非常简单(经过多次重复测试):
- 220 毫秒 对于
mask=(df.T>rowsQuantiles).T
- 65 毫秒 对于
mask=df.apply(lambda row: row > rowsQuantiles)
- 21ms for
df.gt(rowsQuantiles,0)
,已接受的答案。
你的掩码存在转置错误,但假设你想用 NaN 替换值,你正在寻找的方法是 where
:
In [11]: df.T > rowsQuantiles
Out[11]:
0 1 2 3 4 5 6
A True True False False False True True
B False False False True True False False
In [12]: (df.T > rowsQuantiles).T
Out[12]:
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
In [13]: df.where((df.T > rowsQuantiles).T)
Out[13]:
A B
0 5.0 NaN
1 6.0 NaN
2 NaN NaN
3 NaN 5.0
4 NaN 7.0
5 5.0 NaN
6 9.0 NaN
df.apply(lambda row: row > rowsQuantiles)
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
我可以支持的另一种选择是 np.where
:
np.where(df.values > rowsQuantiles[:, None], True, False)
array([[ True, False],
[ True, False],
[False, False],
[False, True],
[False, True],
[ True, False],
[ True, False]], dtype=bool)
哪个 returns 一个 numpy
数组,如果你同意的话。
时间
%timeit df.T > rowsQuantiles
1 loop, best of 3: 251 ms per loop
%timeit df.where((df.T > rowsQuantiles).T)
1 loop, best of 3: 583 ms per loop
%timeit np.where(df.values > rowsQuantiles[:, None], True, False)
10 loops, best of 3: 136 ms per loop
%timeit df.add(-rowsQuantiles,0).gt(0)
10 loops, best of 3: 141 ms per loop
%timeit df.gt(rowsQuantiles,0)
10 loops, best of 3: 25.4 ms per loop
%timeit df.apply(lambda row: row > rowsQuantiles)
10 loops, best of 3: 60.6 ms per loop
也只使用gt
df.gt(rowsQuantiles,0)
Out[288]:
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False
使用add
df.add(-rowsQuantiles,0).gt(0)
Out[284]:
A B
0 True False
1 True False
2 False False
3 False True
4 False True
5 True False
6 True False