如何将Met Office Data Point的JSON天气数据读取到Pandas DataFrame中
如何将Met Office Data Point的JSON天气数据读取到Pandas DataFrame中
嘿,我之前刚好处理过Met Office Data Point的天气数据,这种嵌套的JSON结构确实有点让人头大,我来一步步带你把它转成清爽的Pandas DataFrame,包你一看就会!
第一步:先搞懂JSON的层级结构
首先得摸清楚这个JSON的套路:
- 最外层是
SiteRep,里面Wx下的Param是所有天气参数的定义(比如Dm对应“日间最高气温”,单位是℃) - 真正的天气数据在
DV→Location里,每个Location是一个站点,包含站点ID、名称、经纬度 - 每个站点下的
Period是预报时段(比如按天划分),每个Period里的Rep就是具体的天气数据条目,里面是参数代码和对应的值
第二步:加载JSON数据
先把JSON数据加载到Python里,不管是从本地文件读,还是直接从API请求返回的内容解析,都很简单:
import json import pandas as pd # 情况1:从本地JSON文件加载 with open('met_office_weather.json', 'r', encoding='utf-8') as f: data = json.load(f) # 情况2:直接从API请求获取(用requests库) # import requests # api_key = "你的Data Point API密钥" # target_site_id = "你要查的站点ID" # response = requests.get(f"http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/{target_site_id}?res=3hourly&key={api_key}") # data = response.json()
第三步:预处理参数映射
为了让DataFrame的列名更友好,先把参数代码(比如Dm)转成对应的描述,顺便带上单位:
# 提取参数定义,建立代码到描述、单位的映射 param_list = data['SiteRep']['Wx']['Param'] param_name_map = {p['name']: p['$'] for p in param_list} param_unit_map = {p['name']: p['units'] for p in param_list}
第四步:拆平嵌套数据
这是最关键的一步——把嵌套的JSON数据拆成一行一行的扁平记录,方便转成DataFrame:
weather_records = [] # 遍历每个站点 for location in data['SiteRep']['DV']['Location']: # 提取站点基础信息 site_info = { '站点ID': location['i'], '站点名称': location['name'], '纬度': float(location['lat']), '经度': float(location['lon']) } # 遍历每个预报时段(比如每天) for period in location['Period']: period_date = period['value'] # 时段的日期 # 遍历该时段内的每一条天气记录 for rep in period['Rep']: # 先复制站点和日期信息 record = site_info.copy() record['预报日期'] = period_date # Rep里的$字段是时段偏移(比如360代表从时段开始过了360分钟,也就是6小时) record['时段偏移(分钟)'] = rep.get('$', 0) # 遍历每条记录里的天气参数 for param_code, value in rep.items(): if param_code == '$': continue # 跳过时段偏移字段 # 生成友好的列名,比如"日间最高气温 (℃)" column_name = f"{param_name_map[param_code]} ({param_unit_map[param_code]})" # 把数值转成float,方便后续分析 record[column_name] = float(value) weather_records.append(record)
第五步:转成Pandas DataFrame
最后一步,把整理好的记录列表转成DataFrame,还可以调整列的顺序让它更直观:
df = pd.DataFrame(weather_records) # 调整列的顺序,把基础信息放在前面 base_cols = ['站点ID', '站点名称', '纬度', '经度', '预报日期', '时段偏移(分钟)'] weather_cols = [col for col in df.columns if col not in base_cols] df = df[base_cols + weather_cols] # 看看结果 print(df.head())
小技巧:优化时段显示
如果觉得时段偏移(分钟)不够直观,可以把它转成小时数,或者直接转成具体的时间:
# 把分钟转成小时 df['时段偏移(小时)'] = df['时段偏移(分钟)'].apply(lambda x: int(x) / 60) # 或者根据预报日期+偏移计算具体时间 df['预报时间'] = pd.to_datetime(df['预报日期']) + pd.to_timedelta(df['时段偏移(分钟)'], unit='m')
这样处理完,你就得到了一个结构清晰、字段友好的Pandas DataFrame,不管是做分析还是可视化都很方便!
备注:内容来源于stack exchange,提问作者alecjcook
相关产品推荐
相关产品推荐

