python - 如何(有效地、惯用地)根据条件从熊猫系列中获取元素
问题描述
假设我有一个pandas
Series
对象,并且我想获取其对应值符合某些条件的所有元素(即索引)。
有很多可能的方法可以做到这一点,但我希望有一种简单、有效、惯用的方法——我还没有找到。
这个问题描述了如何使用布尔索引来做到这一点,但这对于一个简单的命令来说似乎过于冗长 - 例如:
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)
或类似的东西,我很惊讶没有找到。
我错过了什么(如果有的话)?提前致谢。
解决方案
对于给定的解决方案,您可以使用 jupyter timeit魔术命令进行一些评估来简单地测试它:
# %%
%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)
推荐阅读
- microsoft-graph-api - Microsoft Teams 中频道和消息级别的自定义数据
- javascript - 如何使用本地存储在网页之间传输值?
- python - 在有向图中查找节点的入度
- wordpress - 使用 Mariadb + NGINX 和自定义 php-fpm Dockerfile 的 WordPress 设置中的权限错误
- aws-lambda - AWS Step Functions 中的状态之间的通信
- sql - 查找按其他两列分组的列的前 n 个总和
- html - 我无法在我的父类中选择我的第二段
- excel - 从下拉列表中选择值时从另一张表中获取记录
- javascript - 如何在ckeditor5中添加音频(自定义)标签
- javascript - 如何从 safeHtml 获取 div 的 id?