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

如何基于列名重组DataFrame,合并多列降雨数据为日期关联单列

Pandas多列逐日降雨数据转日期关联单列格式方案

问题场景

现有一个Pandas DataFrame,包含A、Date(仅记录年月)、C、D字段,以及rain01至rain31共31列字段,分别对应每月1-31日的降雨数据。需要将这些分散的降雨列合并为单列,并关联对应的完整日期,最终得到包含rain、A、C、D、day、month、year的结构化数据。

示例数据

生成示例DataFrame的代码如下:

import pandas as pd
import numpy as np
col = ['A', 'Date', 'C', 'D']
rain_cols = [f'rain{i:02d}' for i in range(1, 32)]
dates = pd.date_range(start='1991-01-01', periods=5, freq='MS')

df = pd.DataFrame({
    'A': np.random.rand(5),
    'Date': dates,
    'C': np.random.rand(5),
    'D': np.random.rand(5)
})

for i in range(1, 32):
    df[f'rain{i:02d}'] = np.random.rand(5)

print(df.head())

示例输出:

A       Date         C         D   rain01   rain02   rain03  ...   rain31
0  0.724846 1991-01-01  0.639414  0.367906  0.917830  0.697984  0.201039  ...  0.241123
1  0.594479 1991-02-01  0.411521  0.960513  0.364190  0.376364  0.911960  ...  0.773762
2  0.597719 1991-03-01  0.853656  0.909157  0.689504  0.619992  0.499380  ...  0.301950
3  0.054729 1991-04-01  0.268398  0.072613  0.202812  0.407357  0.576621  ...  0.959684
4  0.132683 1991-05-01  0.481039  0.216094  0.179478  0.834409  0.459967  ...  0.135629

预期结果

转换后的数据需要按日期排序,每一行对应单日降雨数据,示例如下(1月部分数据):

rain         A         C         D  day  month  year
0  0.718490  0.994329  0.501845  0.311373    1      1  1991
1  0.573670  0.797525  0.279621  0.138967    2      1  1991
2  0.174612  0.065365  0.085481  0.184512    3      1  1991

优化后的解决方案

针对原尝试代码中存在的日期合并问题,以下是优化后的完整实现:

import pandas as pd
import numpy as np

# 生成示例数据(同问题中的代码)
col = ['A', 'Date', 'C', 'D']
rain_cols = [f'rain{i:02d}' for i in range(1, 32)]
dates = pd.date_range(start='1991-01-01', periods=5, freq='MS')

df = pd.DataFrame({
    'A': np.random.rand(5),
    'Date': dates,
    'C': np.random.rand(5),
    'D': np.random.rand(5)
})

for i in range(1, 32):
    df[f'rain{i:02d}'] = np.random.rand(5)

# 1. 执行melt操作,保留所有非降雨列作为ID变量
df_melted = df.melt(
    id_vars=['A', 'Date', 'C', 'D'],
    value_vars=rain_cols,
    var_name='Day_str',
    value_name='rain'
)

# 2. 提取日数:直接取rainXX字段的最后两位转整数
df_melted['Day'] = df_melted['Day_str'].str[-2:].astype(int)

# 3. 生成完整日期:拼接年月字符串与日数字符串,自动过滤无效日期
df_melted['FullDate'] = pd.to_datetime(
    df_melted['Date'].dt.strftime('%Y-%m-') + df_melted['Day'].astype(str),
    errors='coerce'
)

# 4. 清理数据并整理列结构
df_final = df_melted.dropna(subset=['FullDate']).copy()
# 拆分年、月、日字段
df_final['year'] = df_final['FullDate'].dt.year
df_final['month'] = df_final['FullDate'].dt.month
df_final['day'] = df_final['FullDate'].dt.day

# 调整列顺序并排序
df_final = df_final[['rain', 'A', 'C', 'D', 'day', 'month', 'year']]
df_final = df_final.sort_values(by=['year', 'month', 'day']).reset_index(drop=True)

print(df_final.head())

优化说明

  • 保留完整关联字段:melt时将A、C、D都纳入id_vars,避免后续需要重新关联这些字段
  • 高效提取日数:用str[-2:]替代正则提取,代码更简洁且性能更优
  • 自动处理无效日期:通过pd.to_datetime的errors='coerce'参数,自动将不存在的日期(如2月30日、4月31日)转为NaN,再通过dropna过滤
  • 结构化输出:拆分出year、month、day字段,并调整为预期的列顺序,最终数据按日期排序

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:54:56