如何在方法链接表达式中基于其他列的值替换数据子集中的值

2024-04-18 11:15:42 发布

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

我的问题的基本任务是相当琐碎的,当然有许多方法可以做到。但问题的关键部分是如何使用Pandas方法链接表达式。最惯用的方法是什么?你知道吗

考虑这个可复制的例子:

df = pd.DataFrame({'class_size':[1,2,3,4,5,6,7,8,9,10],
                   'num_classes':[100,80,50,40,38,2,1,1,0,0]})

现在您要将class_size大于5的所有行组合在一起,因为超过这一点num_classes非常小。你知道吗

可以根据类大小快速创建一个新列,然后用大于5的值替换其他值。你知道吗

df['grp'] = df.class_size
df.loc[df.class_size > 5, 'grp'] = '> 5'
df

class_size  num_classes grp
0   1   100 1
1   2   80  2
2   3   50  3
3   4   20  4
4   5   10  5
5   6   2   > 5
6   7   1   > 5
7   8   1   > 5
8   9   0   > 5
9   10  0   > 5

很好,这是期望的结果(如我所说,微不足道)。然后,您可以使用新的df生成一个摘要表。你知道吗

df.groupby('grp').agg(
    class_sizes_nunique = ('class_size', 'nunique'), 
    num_classes = ('num_classes', 'sum'),
)

class_sizes_nunique num_classes
grp     
1   1   100
2   1   80
3   1   50
4   1   20
5   1   10
> 5 5   4

现在,在方法链接表达式中实现这一点的最佳方法是什么? 像这样的

(
    df.
    replace_values_in_subset().
    to_other_stuff().
    …
)

我认为,这个约束排除了.loc[]的使用,因为您希望稍后使用整个数据帧(替换一些值,或者在其他列给定的子集中使用具有特定值的新列)。你知道吗

所以我试了一下。你知道吗

我的第一次尝试没有成功,因为错误“一个系列的真值是模糊的”。你知道吗

(
    df.
    assign(grp = lambda x: x.class_size if x.class_size > 5 else x.class_size).
    groupby('grp').agg(
        class_sizes_nunique = ('class_size', 'nunique'), 
        num_classes = ('num_classes', 'sum'),
    )
)

然后我设法得到我想要的结果,将assign()apply()结合起来。你知道吗

(
    df.
    assign(grp = lambda x: x.class_size.apply(lambda y: '> 5' if y > 5 else y)).
    groupby('grp').agg(
        class_sizes_nunique = ('class_size', 'nunique'), 
        num_classes = ('num_classes', 'sum'),
    )
)

这给了我想要的输出,…,但是嵌套lambda的方式看起来很奇怪和复杂。在谷歌上搜索了一下之后,我再也找不到更好的方法了,同样,在方法链的约束下。你知道吗

有什么想法吗?你知道吗


Tags: 方法lambdadfsize链接numaggclass
2条回答

您可以group by一个函数,这样就不需要辅助列:

If by is a function, it’s called on each value of the object’s index

df.set_index('class_size', drop=False).groupby(lambda x: x if x <= 5 else '>5').agg(
        class_sizes_nunique = ('class_size', 'nunique'), 
        num_classes = ('num_classes', 'sum'))

结果:

    class_sizes_nunique  num_classes
1                     1          100
2                     1           80
3                     1           50
4                     1           40
5                     1           38
>5                    5            4

我们可以使用^{}

new_df = (df.assign(grp = df['class_size'].mask(df['class_size'].gt(5),'>5'))
            .groupby('grp').agg(class_sizes_nunique = ('class_size', 'nunique'), 
                                num_classes = ('num_classes', 'sum')
                               )
         )
print(new_df)

输出

     class_sizes_nunique  num_classes
grp                                  
1                      1          100
2                      1           80
3                      1           50
4                      1           40
5                      1           38
>5                     5            4

我们也可以使用^{}

df.assign(grp = df['class_size'].where(df['class_size'].le(5),'>5'))

相关问题 更多 >