如何基于行年份列月份格式的MEI数据绘制时间序列图
MEI时间序列绘图格式解决方案
1. 先把宽格式数据转成长格式
你的df3是行存年份、列存月份组合的宽格式,这种格式不适合时间序列绘图,直接用pd.melt()转成长格式:
import pandas as pd import io import requests import csv import matplotlib.pyplot as plt # 你的原始数据处理代码 url = r"https://psl.noaa.gov/enso/mei/data/meiv2.data" r = requests.post(url) s = r.text df = pd.read_csv(io.StringIO(s), sep=',', header=None, quoting=csv.QUOTE_ALL) df2 = df.drop(index=[0, 46, 47, 48, 49]) df3 = df2[0].str.split('\s+', expand=True) df3.columns = ['Year', 'DJ', 'JF', 'FM', 'MA', 'AM', 'MJ', 'JJ', 'JA', 'AS', 'SO', 'ON', 'ND'] # 转数值类型:年份转整数,MEI值转浮点数 df3['Year'] = df3['Year'].astype(int) for col in df3.columns[1:]: df3[col] = pd.to_numeric(df3[col], errors='coerce') # 宽转长,生成每行对应一个月份组合的MEI数据 df_long = df3.melt(id_vars='Year', var_name='Month_Pair', value_name='MEI')
2. 生成匹配的时间戳
MEI的每个月份组合对应跨月区间,我们给每个组合绑定一个明确的时间点(这里取区间的结束月份,比如DJ对应1月、JF对应2月…ND对应12月):
# 定义月份组合对应的结束月份编号 month_map = { 'DJ': 1, 'JF': 2, 'FM': 3, 'MA': 4, 'AM': 5, 'MJ': 6, 'JJ': 7, 'JA': 8, 'AS': 9, 'SO': 10, 'ON': 11, 'ND': 12 } # 生成时间列 def get_date(row): # 以每个月份组合的结束月份作为时间标记 return pd.Timestamp(year=row['Year'], month=month_map[row['Month_Pair']], day=1) df_long['Date'] = df_long.apply(get_date, axis=1) # 筛选1979-2023年的目标数据 mask = (df_long['Date'] >= '1979-01-01') & (df_long['Date'] <= '2023-12-01') df_plot = df_long[mask].sort_values('Date')
3. 绘制时间序列图
现在df_plot已经是标准的时间序列格式,直接绘图即可:
plt.figure(figsize=(12, 6)) plt.plot(df_plot['Date'], df_plot['MEI'], marker='o', linestyle='-', linewidth=0.8, markersize=3) plt.title('MEI Time Series (1979 DJ - 2023 ND)') plt.xlabel('Date') plt.ylabel('MEI Value') plt.grid(True, alpha=0.3) plt.xticks(rotation=45) plt.tight_layout() plt.show()
关键提示
- 宽转长用
pd.melt()比转置更高效,不用额外处理索引混乱的问题 - 时间戳的标记方式可以按需调整(比如取区间中间日期),只要保持时间顺序一致就行
- 筛选数据时通过
Date列精准控制范围,确保覆盖你需要的1979年DJ到2023年ND区间
内容的提问来源于stack exchange,提问作者Zan
相关产品推荐
相关产品推荐

