pandas含重复日期时如何计算近1000天胜率并填充对应列
实现方案
完全可以计算,重复日期并不会对计算逻辑造成干扰,具体实现思路和代码如下:
前置说明
我们要计算的是每场比赛对应驯马师最近1000天的胜率,核心是用pandas的时间滚动窗口完成分组统计,无需额外处理重复日期,是否包含当前比赛的结果可通过参数灵活调整。
具体步骤
- 第一步:数据预处理,将日期列转为datetime格式,新增
是否获胜标记列(名次为1标记为1,否则为0) - 第二步:按驯马师ID分组,对每个分组的所有比赛按日期升序排序,同日期的比赛会保持原有先后顺序
- 第三步:对每个驯马师的历史数据开启1000天的时间滚动窗口,统计窗口内的胜场总数和参赛总场数
- 第四步:用胜场数除以总场数换算为百分比,即可得到对应的
Win%
代码示例
import pandas as pd # 构造示例数据,实际使用时替换为自己的数据源读取逻辑即可 data = { "日期": ["2017-09-03", "2017-09-16", "2017-10-14", "2017-10-14"], "名次": [4, 5, 1, 3], "驯马师ID": [1788, 1788, 1788, 1788] } df = pd.DataFrame(data) # 1. 预处理 df["日期"] = pd.to_datetime(df["日期"]) df["是否获胜"] = df["名次"].eq(1).astype(int) # 2. 按驯马师分组后按日期排序 df = df.groupby("驯马师ID", group_keys=False).apply( lambda x: x.sort_values("日期", ascending=True, ignore_index=True) ) # 3. 设置日期为索引,开启时间滚动窗口计算 df = df.set_index("日期") # 参数说明:1000D代表1000天窗口,closed='right'代表包含当前行,要排除当前行改为closed='left'即可 roll_window = df.groupby("驯马师ID")["是否获胜"].rolling("1000D", closed="right") df["累计胜场"] = roll_window.sum().reset_index(level=0, drop=True) df["累计参赛"] = roll_window.count().reset_index(level=0, drop=True) # 4. 计算胜率,无历史数据时默认填充0 df["Win%"] = (df["累计胜场"] / df["累计参赛"] * 100).fillna(0).round(0).astype(int) # 恢复日期为普通列,输出结果 df = df.reset_index() print(df[["日期", "名次", "驯马师ID", "Win%"]])
结果验证
运行上述代码得到的输出和给出的示例完全匹配:
| 日期 | 名次 | 驯马师ID | Win% |
|---|---|---|---|
| 2017-09-03 | 4 | 1788 | 0 |
| 2017-09-16 | 5 | 1788 | 0 |
| 2017-10-14 | 1 | 1788 | 33 |
| 2017-10-14 | 3 | 1788 | 25 |
内容的提问来源于stack exchange,提问作者Bogdan Doicin
相关产品推荐
相关产品推荐

