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

.msg文件雨量计数据处理遇故障:脚本运行后列无数据求解

问题诊断与修复方案

你的脚本生成空数据列的核心原因是数据解析逻辑提前终止,未正确读取到雨量计的实际数据。以下是具体问题和修复步骤:

关键问题分析

  1. 空行触发提前终止:在.msg文件的表头行(Gauge Hour Event**)后存在空行,你的代码遇到空行时,line.split()返回空列表,len(parts) !=3会触发break,导致后续实际数据行完全未被处理。
  2. 表头行被误解析为数据:Gauge Hour Event**这一行会被当作雨量计数据处理,尝试将Hour和Event**转为浮点数失败,生成无效的pd.NA条目。

修复后的完整代码

import os
import pandas as pd
from concurrent.futures import ThreadPoolExecutor
from extract_msg import Message

def parse_msg_file(filepath):
    msg = Message(filepath)
    body_lines = msg.body.split('\n')

    # 提取并解析日期时间
    date_str = None
    for line in body_lines:
        stripped_line = line.strip()
        if stripped_line.startswith('Rain Report at '):
            date_str = stripped_line.replace('Rain Report at ', '')
            break

    if not date_str:
        print(f"文件 {filepath} 中未找到日期字符串")
        return []

    try:
        date = pd.to_datetime(date_str)
        date_hour = date.strftime('%m/%d/%Y %H:%M:%S')
    except ValueError:
        print(f"文件 {filepath} 中的日期字符串 '{date_str}' 解析失败")
        return []

    # 解析雨量数据
    data = []
    rain_data_section_started = False
    header_processed = False

    for line in body_lines:
        stripped_line = line.strip()
        # 标记数据段开始
        if stripped_line.startswith('Rain    Past    This'):
            rain_data_section_started = True
            continue

        if rain_data_section_started:
            # 跳过空行
            if not stripped_line:
                continue
            # 跳过表头行(Gauge Hour Event**)
            if stripped_line.startswith('Gauge'):
                header_processed = True
                continue
            # 处理数据行
            parts = line.split()
            if len(parts) == 3:
                gauge, past_hour, this_event = parts
                # 处理数值转换,N/A转为0或pd.NA(根据需求调整)
                try:
                    past_hour = float(past_hour)
                except ValueError:
                    past_hour = 0.0  # 或pd.NA,根据实际需求选择
                try:
                    this_event = float(this_event)
                except ValueError:
                    this_event = 0.0  # 或pd.NA
                data.append((gauge, date_hour, past_hour, this_event))
            else:
                # 遇到非数据行(如后续的Flow Report说明)则终止解析
                break

    return data

# 多线程读取文件
with ThreadPoolExecutor() as executor:
    folder_path = 'C:\\Users\\'  # 替换为你的实际文件夹路径
    filepaths = [os.path.join(folder_path, filename) for filename in os.listdir(folder_path) if filename.endswith('.msg')]

    all_data = []
    for data in executor.map(parse_msg_file, filepaths):
        all_data.extend(data)

# 转换为DataFrame并转置
if all_data:
    df = pd.DataFrame(all_data, columns=['Gauge', 'DateHour', 'Past Hour', 'This Event'])

    # 生成转置后的DataFrame
    df_past_hour = df.pivot(index='Gauge', columns='DateHour', values='Past Hour').fillna(0.0)
    df_this_event = df.pivot(index='Gauge', columns='DateHour', values='This Event').fillna(0.0)

    # 保存到Excel
    with pd.ExcelWriter('C:\\Users\\rain_data4.xlsx') as writer:
        df_past_hour.to_excel(writer, sheet_name='Past Hour')
        df_this_event.to_excel(writer, sheet_name='This Event')
else:
    print("未解析到任何有效雨量数据")

主要修复点说明

  1. 跳过空行:在数据段解析时增加了空行判断,避免空行触发提前终止。
  2. 跳过表头行:专门判断并跳过Gauge开头的表头行,防止误解析。
  3. 空数据检查:在生成Excel前检查all_data是否为空,避免生成空文件。
  4. 填充缺失值:使用fillna(0.0)将转置后的空值填充为0,符合你期望的输出格式(若需要保留pd.NA可删除此部分)。
  5. 健壮性优化:对日期提取增加了strip()处理,避免行首空格导致匹配失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:54:59