我希望按照某些条件对DataFrame进行分组,然后在满足某个谓词的第一行的组( not DataFrame)中找到整数索引。如果没有这样的行,我想获得NaN
。
例如,我按列a
除以5然后在每个组中,找到列b
为“红色”的第一行的索引:
import pandas as pd
import numpy as np
df = pd.DataFrame({'a': xrange(12), 'b': ['red', 'green', 'blue'] * 4})
a b
0 0 red
1 1 green
2 2 blue
3 3 red
4 4 green
5 5 blue
6 6 red
7 7 green
8 8 blue
9 9 red
10 10 green
11 11 blue
df.groupby(df.a // 5).apply(lambda g: next((idx for idx, row in g.reset_index(drop=True).iterrows() if row.b == "red"), None))
a
0 0
1 1
2 NaN
dtype: float64
(我想我假设行保持与原始DataFrame中的顺序相同,但如果需要,我可以对组进行排序。)是否有更简洁,有效的方法来执行此操作?
答案 0 :(得分:2)
这有点长,但恕我直言更容易理解/可定制
In [126]: df2 = df.copy()
这是您的小组指标
In [127]: g = df.a//5
对创建组的引用
In [128]: grp = df.groupby(g)
创建生成的组的列和组中的累积计数
In [129]: df2['group'] = g
In [130]: df2['count'] = grp.cumcount()
In [131]: df2
Out[131]:
a b group count
0 0 red 0 0
1 1 green 0 1
2 2 blue 0 2
3 3 red 0 3
4 4 green 0 4
5 5 blue 1 0
6 6 red 1 1
7 7 green 1 2
8 8 blue 1 3
9 9 red 1 4
10 10 green 2 0
11 11 blue 2 1
过滤和分组可以为您提供所需的第一个元素。计数是组内计数
In [132]: df2[df2.b=='red'].groupby('group').first()
Out[132]:
a b count
group
0 0 red 0
1 6 red 1
您可以生成所有组密钥(例如,您的过滤器没有返回任何内容);这样。
In [133]: df2[df2.b=='red'].groupby('group').first().reindex(grp.groups.keys())
Out[133]:
a b count
0 0 red 0
1 6 red 1
2 NaN NaN NaN
答案 1 :(得分:0)
我能做的最好:
import itertools as it
df.groupby(df.a // 5).apply(lambda group: next(it.chain(np.where(group.get_values() == "red")[0], [None])))
唯一真正的区别是对值使用np.where
(因此我希望通常会更快),但您甚至可能只想编写自己的first_where
函数并使用这一点。