求助:用Pandas计算多列汇总DataFrame,统计产品许可证到期与重订量
解决按门店统计许可证到期及季度重购数量的问题
看起来你卡在了分组统计的环节,手动拼接DataFrame确实容易踩覆盖的坑,我帮你梳理下用pandas正确实现的步骤,应该能解决你的问题:
核心思路
不用手动循环每个门店再拼接,直接用groupby按门店分组统计,既能避免覆盖问题,又更高效。关键要先把日期列处理成datetime类型,不然所有日期相关的计算都会出错。
具体代码实现
1. 导入依赖并读取数据
import pandas as pd from datetime import datetime, timedelta # 读取你的数据文件(替换成你的文件路径,比如CSV/Excel) df = pd.read_csv("your_data_file.csv") # 把许可证到期日转换成datetime类型(如果是Excel可以直接用pd.read_excel的parse_dates参数) # 这里的format要匹配你文件里的日期格式,比如'%Y-%m-%d'是YYYY-MM-DD,'%d/%m/%Y'是DD/MM/YYYY df["Licence_ends"] = pd.to_datetime(df["Licence_ends"], format="%Y-%m-%d", errors="coerce") # 处理转换失败的无效日期(可选,比如删除或标记) df = df.dropna(subset=["Licence_ends"])
2. 标记即将到期的产品
先定义“即将到期”的规则,比如接下来30天内,你可以根据需求调整天数:
today = datetime.today() # 即将到期的截止日期:今天往后推30天 expiry_cutoff = today + timedelta(days=30) # 给每条数据标记是否即将到期 df["is_upcoming_expiry"] = df["Licence_ends"].between(today, expiry_cutoff)
3. 按门店统计即将到期数量
# 按门店分组,统计即将到期的产品总数 expiry_by_store = df.groupby("locations")["is_upcoming_expiry"].sum().reset_index() # 重命名列名更直观 expiry_by_store.columns = ["门店", "即将到期产品数量"]
4. 按门店+季度统计可重购数量
把到期日期转换成季度格式(比如2024Q2),再分组统计:
# 生成到期季度列,格式为"YYYYQX" df["expiry_quarter"] = df["Licence_ends"].dt.to_period("Q").astype(str) # 按门店和季度分组,统计可重购的产品数量 reorder_by_store_quarter = df.groupby(["locations", "expiry_quarter"])["products"].count().reset_index() reorder_by_store_quarter.columns = ["门店", "到期季度", "可重新订购产品数量"]
5. 合并结果(可选)
如果想把两个统计结果合并成一张表查看:
final_result = pd.merge(expiry_by_store, reorder_by_store_quarter, on="门店", how="left") print(final_result)
为什么你之前的方法会失败?
你提到手动向空DataFrame添加数据只得到最后一家门店的结果,大概率是循环时直接赋值覆盖了之前的数据,比如:
# 错误示例:每次循环都把temp赋值给空DataFrame,最后只剩最后一个门店的数据 empty_df = pd.DataFrame() for store in df["locations"].unique(): temp = df[df["locations"] == store].groupby(...) empty_df = temp
正确的手动循环方式应该是收集所有子DataFrame,再用pd.concat拼接:
dfs = [] for store in df["locations"].unique(): temp = df[df["locations"] == store].groupby(...).reset_index() dfs.append(temp) final_df = pd.concat(dfs, ignore_index=True)
不过显然用groupby的方法更简洁,不需要手动循环~
示例结果
假设你的数据是这样的:
| products | locations | Licence_ends |
|---|---|---|
| A | 门店1 | 2024-05-10 |
| B | 门店1 | 2024-06-15 |
| C | 门店2 | 2024-05-20 |
| D | 门店2 | 2024-07-01 |
| E | 门店1 | 2024-04-20 |
如果今天是2024-04-15,那么最终结果会是:
| 门店 | 即将到期产品数量 | 到期季度 | 可重新订购产品数量 |
|---|---|---|---|
| 门店1 | 1 | 2024Q2 | 3 |
| 门店2 | 0 | 2024Q2 | 1 |
| 门店2 | 0 | 2024Q3 | 1 |
内容的提问来源于stack exchange,提问作者Bartek Malysz
相关产品推荐
相关产品推荐

