Fork me on GitHub

Pandas分组求和的题目

一道Pandas题目:求和相关

分享一道关于pandas分组求和的题目。

模拟数据

In [1]:

1
2
import pandas as pd
import numpy as np

In [2]:

1
2
3
4
5
df = pd.DataFrame({"col":list("ABCDABCABAD"),
"number":[10,20,0,None,20,None,None,30,0,40,None]},
index=pd.date_range(start="2022-01-01",periods=11)
)
df

数据特点与需求

In [4]:

1
2
3
4
5
6
(df.sort_values(["col","number"],
ascending=[True,True],
inplace=True,
ignore_index=True))

df

特点

根据字段col进行分组可以看到字段number的特点:

  • A的取值全部存在且大于0
  • B的取值存在0和NaN,也存在大于0的数值
  • C的取值有0和NaN
  • D的取值全部为NaN

需求

根据ABCD分组,求出每个取值对应的和:

  • 如果全部为空,则和为空(D)
  • 如果存在数值和空值,则排除空值再求和(BC)
  • 如果全部为数值,直接求和(A)

错误方法

1
2
#df["total"] = df.groupby("col")["number"].transform(sum)
#df

直接使用transform方法,求和只有一个问题:分组的D中全部是空值,但是求和却是0。

想要的结果的是:结果仍是空值NaN。

解法:

使用多个函数解决了:isnull + groupby + concat + drop_dumplictes + merge

需要区分空值和非空值

非空值部分

In [7]:

先把非空值的数据取出来:

1
2
df1 = df[df["number"].isnull() == False]
df1

对上面的数据分组再求和:

1
2
3
4
5
df3 = (df1.groupby("col")["number"]
.sum()
.reset_index()
.rename(columns={"number":"total"}))
df3

空值部分

从df中取出空值部分:

1
2
3
4
df2 = df[df["number"].isnull() == True]
df2.columns = ["col", "total"] # 重新命名,方便后面合并:number---total

df2

对上面的数据根据col字段进行去重:

1
2
3
df2.drop_duplicates("col", inplace=True)

df2

concat合并

同时存在空值和非空值的BC会出现两次:

去重保留第一次出现的数据:

merge合并

将上面的结果df4和原数据df,根据字段col进行合并:

本文标题:Pandas分组求和的题目

发布时间:2022年08月31日 - 16:08

原始链接:http://www.renpeter.cn/2022/08/31/Pandas%E5%88%86%E7%BB%84%E6%B1%82%E5%92%8C%E7%9A%84%E9%A2%98%E7%9B%AE.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Coffee or Tea