You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DataFrame中基于年份和月份名称生成符合条件的日期?

解决Pandas DataFrame中按规则生成日期的问题

问题概述

需要基于DataFrame中的年份(字符串)、月份名称(字符串)和kpi列,生成符合以下规则的日期字符串:

  • 当kpi为SALES时,日期为当月最后一天;
  • 当kpi为SALES QUANTITY时,日期为当月第一天;
  • 需自动判断闰年以确定对应月份的最后一天(如4月/2月的天数);
  • 所有列保持object(字符串)类型。

原代码(仅生成每月1日)

import pandas as pd

df = pd.DataFrame({
    'year': ['2020', '2021', '2020', '2021'],
    'month': ['April', 'April', 'January', 'January'],
    'kpi': ['SALES', 'SALES', 'SALES QUANTITY', 'SALES QUANTITY']
})

# 原逻辑:固定生成每月1日
df['date'] = pd.to_datetime(df['year'] + ' ' + df['month'] + ' 01').dt.strftime('%Y-%m-%d')

修改后的解决方案代码

import pandas as pd
import numpy as np

# 示例输入数据
df = pd.DataFrame({
    'year': ['2020', '2021', '2020', '2021', '2020', '2021'],
    'month': ['April', 'April', 'January', 'January', 'February', 'February'],
    'kpi': ['SALES', 'SALES', 'SALES QUANTITY', 'SALES QUANTITY', 'SALES', 'SALES']
})

# 1. 生成当月第一天的datetime对象
first_day = pd.to_datetime(df['year'] + ' ' + df['month'] + ' 01')

# 2. 生成当月最后一天的datetime对象,自动处理闰年/月份天数差异
last_day = first_day + pd.offsets.MonthEnd(0)

# 3. 根据kpi规则选择日期,转换为字符串(保证object类型)
df['date'] = np.where(
    df['kpi'] == 'SALES',
    last_day.dt.strftime('%Y-%m-%d'),
    first_day.dt.strftime('%Y-%m-%d')
)

# 验证列类型(可选)
print(df.dtypes)

期望输出

year    month             kpi        date
0  2020    April           SALES  2020-04-30
1  2021    April           SALES  2021-04-30
2  2020  January  SALES QUANTITY  2020-01-01
3  2021  January  SALES QUANTITY  2021-01-01
4  2020  February           SALES  2020-02-29
5  2021  February           SALES  2021-02-28

关键说明

  • 自动处理月份天数:pd.offsets.MonthEnd(0)会自动将日期调整为当月最后一天,无需手动判断闰年或月份天数(包括4月固定30天、闰年2月29天等场景)。
  • 高效向量化操作:使用np.where替代apply,避免逐行循环,处理大数据集时效率更高。
  • 保持object类型:通过dt.strftime将datetime对象转换为字符串,确保date列与其他列类型一致。

内容的提问来源于stack exchange,提问作者Abin Benny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:01:12