我有一个pandas系列,包含boolean条目。我想得到一个索引列表,其中的值是True。例如,输入pd.Series([True, False, True, True, False, False, False, True])应该产生输出[0,2,3,7]。我可以用列表理解来做,但是有没有更干净或更快的方法?
True
pd.Series([True, False, True, True, False, False, False, True])
[0,2,3,7]
jpfvwuh41#
>>> s = pd.Series([True, False, True, True, False, False, False, True]) >>> s[s].index Int64Index([0, 2, 3, 7], dtype='int64')
如果需要一个np.array对象,则获取.values
np.array
.values
>>> s[s].index.values array([0, 2, 3, 7])
np.nonzero
>>> np.nonzero(s) (array([0, 2, 3, 7]),)
np.flatnonzero
>>> np.flatnonzero(s) array([0, 2, 3, 7])
np.where
>>> np.where(s)[0] array([0, 2, 3, 7])
np.argwhere
>>> np.argwhere(s).ravel() array([0, 2, 3, 7])
pd.Series.index
>>> s.index[s] array([0, 2, 3, 7])
filter
>>> [*filter(s.get, s.index)] [0, 2, 3, 7]
>>> [i for i in s.index if s[i]] [0, 2, 3, 7]
vd2z7a6w2#
作为rafaelc's answer的补充,下面是以下设置的相应时间(从最快到最慢
import numpy as np import pandas as pd s = pd.Series([x > 0.5 for x in np.random.random(size=1000)])
>>> timeit np.where(s)[0] 12.7 µs ± 77.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> timeit np.flatnonzero(s) 18 µs ± 508 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
布尔索引的时间差真的让我感到惊讶,因为布尔索引通常更常用。
>>> timeit s.index[s] 82.2 µs ± 38.9 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit s[s].index 1.75 ms ± 2.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
如果需要np.array对象,请获取.values
>>> timeit s[s].index.values 1.76 ms ± 3.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
如果你需要一个稍微容易阅读的版本<--不是在原来的答案
>>> timeit s[s==True].index 1.89 ms ± 3.52 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
pd.Series.where
>>> timeit s.where(s).dropna().index 2.22 ms ± 3.32 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) >>> timeit s.where(s == True).dropna().index 2.37 ms ± 2.19 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
pd.Series.mask
>>> timeit s.mask(s).dropna().index 2.29 ms ± 1.43 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) >>> timeit s.mask(s == True).dropna().index 2.44 ms ± 5.82 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> timeit [i for i in s.index if s[i]] 13.7 ms ± 40.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> timeit [*filter(s.get, s.index)] 14.2 ms ± 28.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> timeit np.nonzero(s) ValueError: Length of passed values is 1, index implies 1000.
>>> timeit np.argwhere(s).ravel() ValueError: Length of passed values is 1, index implies 1000.
bxjv4tth3#
也可以使用:s.where(lambda x: x).dropna().index,它的优点是很容易链接管道-如果你的系列是在运行中计算的,你不需要将它分配给一个变量。请注意,如果s是从r计算出来的:s = cond(r)也可以用途:r.where(lambda x: cond(x)).dropna().index。
s.where(lambda x: x).dropna().index
s
r
s = cond(r)
r.where(lambda x: cond(x)).dropna().index
bqujaahr4#
您可以使用pipe或loc来链接操作,当s是中间结果并且您不想命名它时,这很有帮助。
pipe
loc
s = pd.Series([True, False, True, True, False, False, False, True], index=list('ABCDEFGH')) out = s.pipe(lambda s_: s_[s_].index) # or out = s.pipe(lambda s_: s_[s_]).index # or out = s.loc[lambda s_: s_].index
print(out) Index(['A', 'C', 'D', 'H'], dtype='object')
4条答案
按热度按时间jpfvwuh41#
使用布尔索引
如果需要一个
np.array
对象,则获取.values
使用
np.nonzero
使用
np.flatnonzero
使用
np.where
使用
np.argwhere
使用
pd.Series.index
使用Python内置的
filter
使用列表解析
vd2z7a6w2#
作为rafaelc's answer的补充,下面是以下设置的相应时间(从最快到最慢
使用
np.where
使用
np.flatnonzero
使用
pd.Series.index
布尔索引的时间差真的让我感到惊讶,因为布尔索引通常更常用。
使用布尔索引
如果需要
np.array
对象,请获取.values
如果你需要一个稍微容易阅读的版本<--不是在原来的答案
使用
pd.Series.where
<--不在原始答案中使用
pd.Series.mask
<--不在原始答案中使用列表解析
使用Python内置的
filter
使用
np.nonzero
<--对我来说并不适用使用
np.argwhere
<--对我来说并不适用bxjv4tth3#
也可以使用:
s.where(lambda x: x).dropna().index
,它的优点是很容易链接管道-如果你的系列是在运行中计算的,你不需要将它分配给一个变量。请注意,如果
s
是从r
计算出来的:s = cond(r)
也可以用途:r.where(lambda x: cond(x)).dropna().index
。bqujaahr4#
您可以使用
pipe
或loc
来链接操作,当s
是中间结果并且您不想命名它时,这很有帮助。