使用Pandas清洗文本文件并导出为CSV的技术问题求助
解决Aberporth气象数据文本的清洗与列处理问题
不用换工具!Pandas完全能搞定这个问题,核心是要先处理多空格分隔和中途新增列这两个关键点,我给你梳理下具体步骤和代码:
1. 先理清数据格式的坑
这个Met Office的文本文件有两个典型问题:
- 列分隔是多个连续空格,不是单个空格,直接用
sep=" "会把单个空格当成分隔符,导致列识别混乱; - 第944行左右新增了一列,导致前后行的列数不一致,直接用
read_csv会报错或丢失数据。
2. 分步处理的解决方案
步骤1:获取文本内容并拆分行
先把整个文本拉下来,按行拆分,方便后续分批次处理不同列数的行:
import pandas as pd import requests import io import re # 获取数据文本 URLH = "https://www.metoffice.gov.uk/pub/data/weather/uk/climate/stationdata/aberporthdata.txt" with requests.session() as s: r = s.get(URLH) # 按行拆分文本,过滤空行 lines = [line.strip() for line in r.text.splitlines() if line.strip()]
步骤2:提取位置和经纬度信息
从文本开头的说明行里提取站点名称、纬度、经度:
# 提取站点名称(第一行) location = lines[0] # 提取经纬度(第二行,格式类似"Location: 52.18N 4.51W, 133m amsl") lat_lon_match = re.search(r'(\d+\.\d+[NS]) (\d+\.\d+[EW])', lines[1]) lat, lon = lat_lon_match.groups()
步骤3:拆分不同列数的数据行
跳过前5行说明,把剩下的行分成「7列组」和「8列组」:
# 跳过前5行说明内容,从第6行开始是数据 data_lines = lines[5:] # 拆分两种列数的行 rows_7cols = [] rows_8cols = [] for line in data_lines: # 按任意空白符拆分,得到列数据 parts = re.split(r'\s+', line) if len(parts) == 7: rows_7cols.append(parts) elif len(parts) == 8: rows_8cols.append(parts)
步骤4:分别构建DataFrame并合并
给两种列数的行指定对应的列名,然后合并(新增列的名称可以根据原文件实际内容调整,比如查看后发现是Frost_Days):
# 7列的列名(对应新增列之前的行) cols_7 = ['Year', 'Month', 'Tmax', 'Tmin', 'Tmean', 'Rain', 'Sun'] # 8列的列名(包含新增列) cols_8 = ['Year', 'Month', 'Tmax', 'Tmin', 'Tmean', 'Rain', 'Sun', 'Frost_Days'] # 构建DataFrame df_7 = pd.DataFrame(rows_7cols, columns=cols_7) df_8 = pd.DataFrame(rows_8cols, columns=cols_8) # 合并两个DataFrame,缺失的列自动填充NaN df = pd.concat([df_7, df_8], ignore_index=True)
步骤5:清洗数据并添加额外列
处理缺失值、转换数据类型,再添加之前提取的位置、经纬度列:
# 把缺失值标记'---'替换为NaN df.replace('---', pd.NA, inplace=True) # 处理带特殊标记的数值(比如*、#),去掉符号后转成数值类型 for col in ['Tmax', 'Tmin', 'Tmean', 'Rain', 'Sun', 'Frost_Days']: if col in df.columns: df[col] = df[col].str.replace(r'[*#]', '', regex=True).astype(float) # 添加额外的三列 df['location'] = location df['lat'] = lat df['lon'] = lon
步骤6:导出为CSV
df.to_csv('Aberporth_cleaned.csv', sep='|', index=False)
为什么不用换工具?
Pandas配合简单的正则预处理,完全能应对这种格式不规整的文本文件。核心是先把不同列数的行拆分处理,再合并,而不是强行用read_csv一次性读取。
内容的提问来源于stack exchange,提问作者user11754953
相关产品推荐
相关产品推荐

