You need to enable JavaScript to run this app. 如何将双空格分隔的分块日历数据转换为pandas日期时间数据框
优惠活动
大模型
产品
解决方案
定价
更多

如何将双空格分隔的分块日历数据转换为pandas日期时间数据框

分块日历文本转结构化长表实现方案

核心解析思路

常规印刷版分块日历的文本结构一般符合以下特征,也是我们解析的适配基础:

  • 按月份独立分块,每个块的开头是月份标识行(比如2021年1月这类文本)
  • 块内第二行是固定7列的星期表头,对应周一到周日
  • 块内后续行是每周的日期单元格,每个有效单元格的内容格式是「日期数字 + 对应时间值y」(比如1 17:26),非当月的占位单元格无有效y值
  • 所有日期、数值没有连续排列,完全分散在不同块、不同行列位置,不适合直接用固定列结构的CSV读取方式处理

可落地实现代码

1. 基础依赖导入与全量文本读取

跳过固定列结构的CSV读取,直接加载所有非空文本行,避免列错位问题:

import pandas as pd
import re

# 读取本地文本文件的所有非空行,去除前后冗余空白
with open("2021.txt", "r", encoding="utf-8") as f:
    raw_lines = [line.strip() for line in f.readlines() if line.strip()]

2. 逐行解析块结构,提取有效记录

遍历所有文本行,匹配月份边界、拆分单元格内容、过滤无效占位值:

extracted_records = []
current_month = None
# 匹配月份标识的正则:识别类似"2021年X月"的行
month_matcher = re.compile(r"2021年(\d{1,2})月")
# 匹配有效单元格的正则:识别"日期 时间"格式的单元格内容
cell_matcher = re.compile(r"^\s*(\d{1,2})\s+(\d{1,2}:\d{2})\s*$")

for line in raw_lines:
    # 检测当前行是否为月份标题,更新当前解析的月份
    month_match = month_matcher.search(line)
    if month_match:
        current_month = int(month_match.group(1))
        continue
    # 跳过星期表头行
    if re.search(r"[一二三四五六日]\s+[一二三四五六日]", line):
        continue
    # 按2个以上连续空白拆分当前行的所有单元格,兼容不同缩进的排版
    line_cells = re.split(r"\s{2,}", line)
    for cell in line_cells:
        cell_match = cell_matcher.search(cell)
        if not cell_match:
            continue
        # 提取单元格内的日、y值,做基础合法性校验
        day = int(cell_match.group(1))
        y_value = cell_match.group(2)
        if 1 <= day <= 31 and current_month is not None:
            extracted_records.append({
                "month": current_month,
                "day": day,
                "y": y_value
            })

3. 生成标准日期列,整理最终长表

使用pandas.to_datetime拼接生成符合要求的标准日期格式,整理为目标两列结构:

# 转成临时数据框
temp_df = pd.DataFrame(extracted_records)
# 拼接完整日期字符串,转成标准datetime格式
temp_df["Date"] = pd.to_datetime(
    "2021-" + temp_df["month"].astype(str) + "-" + temp_df["day"].astype(str),
    format="%Y-%m-%d"
)
# 按日期排序,取目标列得到最终结果
result_df = temp_df[["Date", "y"]].sort_values("Date").reset_index(drop=True)

避坑提示

  • 直接用pd.read_csv(sep=" ")的方案容错性很差:因为日历排版的缩进不固定,相邻单元格的分隔空格数经常变化,很容易出现值串行、列错位的问题,逐块解析的方式能适配绝大多数排版差异
  • 一定要做单元格有效性校验:印刷日历通常会在月初、月末的单元格打印相邻月份的日期占位,这类单元格没有对应y值,通过正则匹配可以自动过滤,不会混进最终结果
  • 日期拆分逻辑不需要额外处理补零:pd.to_datetime会自动识别个位数的月、日格式,不用手动给月、日补0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.10 22:45:07