如何基于Pandas DataFrame时间戳列生成对应月度的所有日期
问题:为Pandas DataFrame按分组生成对应月份的所有日期列
现有包含Id、timestamp、Value列的Pandas DataFrame,需要按Id分组,根据timestamp列对应的月份,在新列ext_dtes中生成该月所有日期(30天的月份生成30行、31天的月份生成31行、28天的月份生成28行),日期格式为dd-mm-yyyy。
输入输出示例
输入DataFrame
Id timestamp Value 1002 18-01-2021 45 1003 08-03-2021 14 1004 03-07-2021 50 1005 18-06-2021 23 1005 12-09-2021 108
输出DataFrame
Id timestamp Value ext_dtes 1002 18-01-2021 45 01-01-2021 1002 18-01-2021 45 02-01-2021 ... ... ... ... 1002 18-01-2021 45 31-01-2021 ... ... ... ...
现有代码的错误分析
尝试代码1的问题
date_format = [datetime.strptime(i, '%d-%m-%Y') for i in df['timestamp']] num_days = [calendar.monthrange(i.year,i.month,i.date)[2] for i in date_format] num_days df['ext_dates']= df.groupby(pd.PeriodIndex(data= num_days, freq='D'))
calendar.monthrange()仅接受年份和月份两个参数,传入第三个参数i.date会触发参数不匹配错误- 直接将
groupby对象赋值给DataFrame列是错误操作,groupby对象不是可直接赋值的序列类型
尝试代码2的问题
import pandas as pd df_a['Timestamp'] = pd.to_datetime(df_a['Timestamp']) month =df_a['Timestamp'] df = pd.DataFrame({ 'all_dates': pd.date_range( start = pd.Timestamp(month), end = pd.Timestamp(month) + pd.offsets.MonthEnd(0), freq = 'D' ) })
pd.Timestamp()只能处理单个日期值,而month是Series类型(整列数据),无法直接转换,因此抛出TypeError: 无法将 <class 'pandas.core.series.Series'> 类型的输入转换为Timestamp
正确解决方案
步骤:
- 转换
timestamp列为datetime类型,方便后续日期操作 - 对每行数据,生成对应月份的完整日期范围
- 展开日期列表,保留原行的
Id、timestamp、Value列 - 将生成的日期格式化为
dd-mm-yyyy字符串
完整代码:
import pandas as pd # 构造输入DataFrame df = pd.DataFrame({ 'Id': [1002, 1003, 1004, 1005, 1005], 'timestamp': ['18-01-2021', '08-03-2021', '03-07-2021', '18-06-2021', '12-09-2021'], 'Value': [45, 14, 50, 23, 108] }) # 1. 转换timestamp列为datetime类型 df['timestamp'] = pd.to_datetime(df['timestamp'], format='%d-%m-%Y') # 2. 定义函数:根据日期生成对应月份的所有日期 def generate_month_dates(row): # 获取当月第一天 month_start = row['timestamp'].replace(day=1) # 获取当月最后一天 month_end = row['timestamp'] + pd.offsets.MonthEnd(0) # 生成日期范围并转为列表 return pd.date_range(start=month_start, end=month_end, freq='D').tolist() # 3. 应用函数生成日期列表,然后展开行 df['ext_dtes'] = df.apply(generate_month_dates, axis=1) df_expanded = df.explode('ext_dtes', ignore_index=True) # 4. 格式化日期列为dd-mm-yyyy格式 df_expanded['ext_dtes'] = df_expanded['ext_dtes'].dt.strftime('%d-%m-%Y') # 可选:将原timestamp列转回字符串格式(如果需要和输入格式一致) df_expanded['timestamp'] = df_expanded['timestamp'].dt.strftime('%d-%m-%Y') print(df_expanded)
这段代码会将原DataFrame的每一行,根据其timestamp对应的月份,扩展为该月天数的行数,同时保留原行的所有信息,并生成符合要求的ext_dtes列。
内容的提问来源于stack exchange,提问作者seek
相关产品推荐
相关产品推荐

