看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
本案例的数据为一个分组数据,每个分组内包含几个指标和指标的值,组内最后一个指标为前边所有指标的总体,需求期望将前边的这些指标作为分子,总体作为分母,无需计算只要以字符串的形式显示这个分数即可。同时,前边的指标与这个总体指标也用下划线连接显示。接下来我们用 pandas 来解决这个问题。
我们来构造数据和描述一下需求,数据为:
import pandas as pd
import random
random.seed(7890)
data = {
    'A': ['x']*4 + ['y']*4,
    'B': [*'abcD']*2,
    'C': [random.randint(1,9) for i in range(8)],
}
df = pd.DataFrame(data)
df
'''
   A  B  C
0  x  a  4
1  x  b  7
2  x  c  1
3  x  D  7
4  y  a  3
5  y  b  5
6  y  c  2
7  y  D  6
'''
A 列为分组,B 列为指标,其中最后一个指标 D 为总体,C 列为指标的值。最终期望生成的新数据如:
'''
   A    B    C
0  x  a_D  4/7
1  x  b_D  7/7
2  x  c_D  1/7
4  y  a_D  3/6
5  y  b_D  5/6
6  y  c_D  2/6
'''
B 列由指标和总体指标(分组最后一个,名称不确定)连接而成,C 列由指标值和总体指标值连接而成。 分组内的总体指标列不需要显示,即没有 D_D 数据。
由于需求是分组需求,我们对数据分组后,每个分组就是一个单独的子 DataFrame,我们定义一个函数来用 apply() 调用,在函数中处理需求逻辑。
在这个处理函数中,我们接受的是一个 DataFrame,B 列和 C 列进行字符拼接,最后再将这些数据生成 DataFrame 返回。
定义分组后单个 DataFrame 数据的处理函数:
def func(grp: pd.DataFrame):
    b, c = grp.B, grp.C.astype(str)
    b = b.iloc[:-1] + '_' + b.iat[-1]
    c = c.iloc[:-1] + '/' + c.iat[-1]
    return pd.DataFrame({'A': grp.name, 'B': b, 'C': c})
函数中,以 B 列为例,先选择此列的列包含最后一个数据的所有数据(Series,用 iloc[:-1]),再选择此列的最后一个值(单个值用 iat[-1]),然后用 + 法 ( add() 方法)进行拼接。C 列是数字类型,要先转为字符才可拼接。
返回数据的 A 列值 grp.name 中的 name 属性是分组对象子 DataFrame 的分组名,这是分组过程中增加的特有属性。
最终分组调用函数代码:
df.groupby('A', group_keys=False).apply(func)
'''
   A    B    C
0  x  a_D  4/7
1  x  b_D  7/7
2  x  c_D  1/7
4  y  a_D  3/6
5  y  b_D  5/6
6  y  c_D  2/6
'''
代码中 group_keys=False 不保留分组名为索引,保证返回的数据和原数据结构一样。
这样就完成了需求。
(完)
更新时间:2024-08-18 15:55:47 标签:pandas python 分数 分组