如何将Delft-FEWS时间序列XML文档加载为pandas DataFrame
解决方案
你可以通过xml.etree.ElementTree解析XML结构后拼接数据转DataFrame,完整实现步骤如下:
1. 导入依赖
import xml.etree.ElementTree as ET import pandas as pd
2. 解析XML并处理命名空间(最容易踩的坑)
该XML文档自带PI命名空间,直接通过标签名查找会返回空结果,需要先声明命名空间映射:
# 读取本地XML文件用ET.parse,接口返回的字符串直接用ET.fromstring(响应内容) tree = ET.parse("你的XML文件路径.xml") root = tree.getroot() # 声明命名空间映射 ns = {"pi": "http://www.wldelft.nl/fews/PI"}
3. 遍历节点拼接数据
逐组读取series的公共头信息,再将头信息拼到每个event观测记录中:
res = [] for series in root.findall("pi:series", ns): # 提取当前序列的公共属性 header = series.find("pi:header", ns) loc_id = header.find("pi:locationId", ns).text param_id = header.find("pi:parameterId", ns).text # 其他header字段如站点名、单位等可按同样规则自行提取 # 遍历所有观测记录 for event in series.findall("pi:event", ns): # 拼接日期时间并转格式 dt = pd.to_datetime(f"{event.get('date')} {event.get('time')}") res.append({ "datetime": dt, "location_id": loc_id, "parameter_id": param_id, "value": float(event.get("value")), "flag": int(event.get("flag")) })
4. 转成DataFrame
df = pd.DataFrame(res) # 可选:将时间设为索引方便后续时间序列操作 df = df.set_index("datetime")
常见注意事项
- 命名空间不能省略,所有标签查找都要带上之前定义的
pi前缀 - 读取到的
value和flag默认是字符串格式,要手动转成数值类型才能用于后续计算 - 如果XML中
timeZone字段不是0,转时间的时候要补充对应的时区偏移,避免时间出现错位 - 如果需要保留header里的其他字段,按照
locationId的提取规则添加即可
内容的提问来源于stack exchange,提问作者Grismar
相关产品推荐
相关产品推荐

