Pandas按索引分组

4

我有一个数据框,其中有一列我想要按组分组。在每组内,我想进行一个检查,看看第一个值是否小于第二个值乘以某个标量,例如(x < y * .5)。如果是,则将第一个值设置为True,所有其他值都为False。否则,所有值都为False。

我这里有一个示例数据框:

d = pd.DataFrame(np.array([[0, 0, 1, 1, 2, 2, 2],
                           [3, 4, 5, 6, 7, 8, 9],
                           [1.25, 10.1, 2.3, 2.4, 1.2, 5.5, 5.7]]).T,
                          columns=['a', 'b', 'c'])

我可以使用分组堆叠来获取我想要的a数据:

g = d.groupby('a')['c'].nsmallest(2).groupby(level='a')

这导致分成三个组,每组有两个条目。通过添加apply,我可以调用一个函数返回一个布尔掩码:
def func(group):
    if group.iloc[0] < group.iloc[1] * .5:
        return [True, False]
    else:
        return [False, False]

g = d.groupby('a')['c'].nsmallest(2).groupby(level='a').apply(func)

很不幸,这会破坏原始数据框中的索引,并且无法处理存在超过2个元素的情况。

有两个问题:

  1. 是否可能保留原始数据框中的索引并更新一列以显示groupby的结果?这因为 .nsmallest 调用在“c”列上生成了 series,所以有所不同。

  2. 是否存在更优雅的方法来计算基于自定义条件(例如此比率测试)的数据框中的组的布尔数组?

1个回答

2

看起来你需要使用transform函数:

>>> def func(group):
...     res = [False] * len(group)
...     if group.iloc[0] < group.iloc[1] * .5:
...         res[0] = True
...     return res
>>> d['res'] = d.groupby('a')['c'].transform(func).astype('bool')
>>> d
   a  b      c    res
0  0  3   1.25   True
1  0  4  10.10  False
2  1  5   2.30  False
3  1  6   2.40  False
4  2  7   1.20   True
5  2  8   5.50  False
6  2  9   5.70  False

来自文档:

transform方法返回一个与被分组的对象相同(大小相同)的对象。因此,传递的transform函数应该返回一个与组块大小相同的结果。例如,假设我们希望在每个组内标准化数据。


工作得很好。我之前没有意识到 transform 可以接受任意函数(在文档中漏掉了)。谢谢! - Jzl5325

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接