如何(有效地、惯用地)根据条件从pandas系列中提取元素

2024-06-09 00:50:18 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个pandasSeries对象,我想获取其对应值符合某种条件的所有元素(意义索引)。你知道吗

有很多可能的方法可以做到这一点,但我希望有一个简单,有效,惯用的方法-我还没有找到。你知道吗

This question描述了如何使用布尔索引进行索引,但是对于一个简单的命令来说,这似乎过于冗长了—例如:

import pandas as pd

age = pd.Series(index=['mom','dad','cat1','cat2','baby'],
                data=[30,30,3,3,1])

age[age>10].index.values

[编辑:注意变量名age在前一行中出现了两次。当然age[age>10]很短,但这只是因为age是一个短名称-如果我遇到一个长名称的序列,比如age_of_family_members_after_filtering,那么age_of_family_members_after_filtering[age_of_family_members_after_filtering>10]看起来就不太好了。你知道吗

我发现的其他解决方案同样冗长:

age.where(lambda x: x>10).dropna().index.values

或:

[name for name, _age in age.items() if _age>10]

(最后一个返回一个列表,而前一个返回数组,但这两个都可以)

因为这是一个非常常见的命令,所以我希望使用age.filter_where(lambda x: x>10)或类似的命令,我很惊讶没有找到这样的命令。你知道吗

我错过了什么(如果有的话)? 提前谢谢。你知道吗


Tags: of方法lambda命令名称ageindexwhere
3条回答

对于给定的解决方案,您可以使用jupytertimeitmagic命令进行一些评估,以简单地对其进行测试:

# %%
%timeit age[age>10].index.values
--> 235 µs ± 8.68 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


# %%
%timeit age.where(lambda x: x>10).dropna().index.values
--> 510 µs ± 14.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# %%
%timeit [name for name, _age in age.items() if _age>10]
--> 12.5 µs ± 429 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

对于给定的解,最后一个是最快的,但是第一个是最简单的,仍然是完全有效的。你知道吗

另一个,注意效率的不同:

age.index[age.values > 10].tolist()
--> 16.5 µs ± 823 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

age.index[age > 10].tolist()
--> 157 µs ± 12.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)


更新@Alexander的想法:

# %% 
from itertools import compress
%timeit list(compress(age.index, age > 10))
--> 119 µs ± 3.24 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

pandas中的行切片接受callable。所以你可以

age.loc[lambda x: x > 10]

这个小例子看起来有点过分,但是:

  • 如果序列名不是age,而是series_long_after_operation,这就变得更清楚了
  • 它支持方法链接,如age.loc[lambda x: x > 10].loc[lambda x: x%2==0]

第二种方法实际上是长管道操作的一种方法,其中每个方法都返回不同的数据帧形状。你知道吗

你可以压缩索引,但我不认为它比简单的布尔索引更简单,因为布尔索引非常简洁

from itertools import compress

>> list(compress(age.index, age > 10))
['mom', 'data']

相关问题 更多 >