Python绘制时间序列与地理地图数据可视化实例
一、环境准备与核心依赖栈
进行时空数据可视化前,需要配置合适的基础库环境。处理时间序列主要依赖 pandas(用于时序索引与聚合)与 matplotlib(基础渲染底座);处理地理空间数据则需要 geopandas(基于Shapely和GDAL的矢量处理库)以及 contextily(可选,用于加载Web地图底图)。
建议在干净的虚拟环境中执行以下安装命令:
pip install pandas matplotlib geopandas shapely
如果在Windows或特定Linux环境中安装 geopandas 遇到编译底层C依赖(GDAL/GEOS)的问题,建议使用 conda install -c conda-forge geopandas 进行安装,由Conda自动解决二进制动态链接库依赖。
二、时间序列数据可视化实例
绘制时间序列的核心并非仅仅是把日期作为X轴画一条折线,而在于对时间维度的结构化处理,包括日期格式标准化、设定DatetimeIndex、周期性重采样以及滚动统计特征的叠加呈现。
2.1 时间序列绘制完整示例代码
下面是一个包含真实观测模拟、滚动平均(Rolling Average)、波动带填充(Confidence Interval)及日期自适应刻度的完整脚本:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
# 1. 模拟生成连续90天的逐小时时序数据
np.random.seed(42)
dates = pd.date_range(start="2024-01-01", periods=90 * 24, freq="h")
# 生成基准正弦波周期信号 + 趋势 + 随机扰动
trend = np.linspace(20, 35, len(dates))
seasonal = 8 * np.sin(2 * np.pi * dates.hour / 24)
noise = np.random.normal(0, 3, size=len(dates))
values = trend + seasonal + noise
df = pd.DataFrame({"timestamp": dates, "load": values})
df.set_index("timestamp", inplace=True)
# 2. 时序聚合:按日重采样并计算均值、滚动指标与标准差
daily_df = df.resample("D").mean()
daily_df["rolling_7d"] = daily_df["load"].rolling(window=7, min_periods=1).mean()
daily_df["std_7d"] = daily_df["load"].rolling(window=7, min_periods=1).std().fillna(0)
# 3. 创建图表画布
fig, ax = plt.subplots(figsize=(12, 5), dpi=120)
# 绘制日均散点、周滚动趋势线与波动区间
ax.plot(daily_df.index, daily_df["load"], color="#5a646e", linestyle="--", alpha=0.6, label="每日均值")
ax.plot(daily_df.index, daily_df["rolling_7d"], color="#b96555", linewidth=2.5, label="7日滑动平均趋势")
ax.fill_between(
daily_df.index,
daily_df["rolling_7d"] - daily_df["std_7d"],
daily_df["rolling_7d"] + daily_df["std_7d"],
color="#b96555",
alpha=0.15,
label="7日波动区间 (±1σ)"
)
# 4. 坐标轴格式化
ax.xaxis.set_major_locator(mdates.WeekdayLocator(interval=2))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
fig.autofmt_xdate(rotation=30, ha="right")
ax.set_title("电力负荷时间序列监测与趋势平滑实例", fontsize=14, pad=12)
ax.set_xlabel("监测日期", fontsize=11)
ax.set_ylabel("负荷数值 (MW)", fontsize=11)
ax.grid(True, linestyle=":", alpha=0.5)
ax.legend(loc="upper left", frameon=True)
plt.tight_layout()
plt.show()
三、地理地图数据可视化实例
绘制地图不仅是画出经纬度点,更重要的是理解“地理图层结构”与“坐标参考系(CRS)”。一个标准的地图可视化由几何矢量边界、数据属性字段以及投影对齐系统组成。
3.1 地理区域分级色彩图(Choropleth)完整示例
以下示例演示如何构建包含几何形状的 GeoDataFrame,为各区域绑定指标,并绘制带有颜色映射图例(Colorbar)的标准分级统计地图:
import geopandas as gpd
import matplotlib.pyplot as plt
from shapely.geometry import Polygon, Point
# 1. 模拟构建四个相邻区域的地理多边形(Polygon)
poly1 = Polygon([(116.2, 39.9), (116.4, 39.9), (116.4, 40.1), (116.2, 40.1)])
poly2 = Polygon([(116.4, 39.9), (116.6, 39.9), (116.6, 40.1), (116.4, 40.1)])
poly3 = Polygon([(116.2, 39.7), (116.4, 39.7), (116.4, 39.9), (116.2, 39.9)])
poly4 = Polygon([(116.4, 39.7), (116.6, 39.7), (116.6, 39.9), (116.4, 39.9)])
gdf_regions = gpd.GeoDataFrame({
"region_name": ["西北区", "东北区", "西南区", "东南区"],
"business_index": [78.5, 92.0, 64.2, 85.3],
"geometry": [poly1, poly2, poly3, poly4]
}, crs="EPSG:4326")
# 2. 模拟散点业务事件(经纬度点)
pts = [Point(116.32, 39.95), Point(116.51, 40.02), Point(116.28, 39.81), Point(116.45, 39.88)]
gdf_points = gpd.GeoDataFrame({
"site_id": ["S1", "S2", "S3", "S4"],
"alerts": [5, 18, 2, 9],
"geometry": pts
}, crs="EPSG:4326")
# 3. 绘制分级设色多边形与事件散点
fig, ax = plt.subplots(figsize=(8, 7), dpi=120)
# 底层面要素:根据 business_index 上色
gdf_regions.plot(
column="business_index",
cmap="YlOrRd",
linewidth=0.8,
edgecolor="#30363c",
legend=True,
legend_kwds={"label": "区域综合业务景气度", "orientation": "horizontal", "shrink": 0.7, "pad": 0.05},
ax=ax
)
# 顶层点要素:点大小映射告警量 alerts
gdf_points.plot(
ax=ax,
color="#30363c",
markersize=gdf_points["alerts"] * 15,
alpha=0.85,
label="重点监测站点"
)
# 标注文字
for idx, row in gdf_regions.iterrows():
centroid = row.geometry.centroid
ax.text(centroid.x, centroid.y, row["region_name"], ha="center", va="center", fontsize=10, weight="bold")
ax.set_title("区域业务指数分级与重点站点空间分布", fontsize=13, pad=12)
ax.set_xlabel("经度 (Longitude)", fontsize=10)
ax.set_ylabel("纬度 (Latitude)", fontsize=10)
ax.legend(loc="upper right")
ax.grid(True, linestyle="--", alpha=0.3)
plt.tight_layout()
plt.show()
四、时空联合分析:结合时间序列与地理特征
真实业务场景中,时间序列与地理空间往往不是孤立的。例如监测不同区域的月度指标演变、气象站点的气温时序变化等。实现时空联合可视化的最佳实践包括:
- 多子图小面板(Small Multiples):通过固定空间范围的网格切片展示不同时间切片,利于快速横向比对空间格局演化。
- 联动双面板视图(Linked Dual-Panel):主界面左侧为空间多边形/散点分布图,右侧为选定区域或全部区域的时间序列走势对比图。
4.1 空间-时序联动双视窗代码实例
下面代码构建了一个综合图表:左视窗展示区域最新空间评分分级,右视窗展示各区域近半年的历史演化时序曲线,两边颜色完全统一对应。
import pandas as pd
import numpy as np
import geopandas as gpd
import matplotlib.pyplot as plt
from shapely.geometry import box
# 1. 生成空间网格(三个大区)
regions = ["华北区", "华东区", "华南区"]
polys = [
box(115, 38, 120, 42),
box(118, 30, 123, 34),
box(112, 22, 117, 26)
]
gdf = gpd.GeoDataFrame({"region": regions, "geometry": polys}, crs="EPSG:4326")
# 2. 生成各区域的月度时序指标
dates = pd.date_range("2024-01-01", periods=6, freq="MS")
palette = {"华北区": "#30363c", "华东区": "#b96555", "华南区": "#5a646e"}
ts_data = {
"华北区": [62, 65, 68, 71, 75, 79],
"华东区": [80, 83, 82, 88, 91, 95],
"华南区": [70, 72, 71, 74, 76, 78]
}
# 3. 创建双栏子图
fig, (ax_geo, ax_ts) = plt.subplots(1, 2, figsize=(14, 6), dpi=120)
# 绘制左侧地图
for idx, row in gdf.iterrows():
color = palette[row["region"]]
gpd.GeoSeries(row.geometry).plot(ax=ax_geo, color=color, edgecolor="#ffffff", linewidth=2, alpha=0.85)
c = row.geometry.centroid
ax_geo.text(c.x, c.y, row["region"], color="#ffffff", weight="bold", ha="center", va="center", fontsize=11)
ax_geo.set_title("各区域地理区位与空间分布", fontsize=13, pad=10)
ax_geo.set_xlabel("经度")
ax_geo.set_ylabel("纬度")
ax_geo.grid(True, linestyle=":", alpha=0.4)
# 绘制右侧时序图
for r_name in regions:
ax_ts.plot(dates, ts_data[r_name], marker="o", linewidth=2.2, color=palette[r_name], label=r_name)
ax_ts.set_title("各区域月度景气指数时序走势对比", fontsize=13, pad=10)
ax_ts.set_xlabel("月份")
ax_ts.set_ylabel("综合指数 (分)")
ax_ts.grid(True, linestyle=":", alpha=0.5)
ax_ts.legend(loc="upper left")
plt.tight_layout()
plt.show()
五、生产实践注意事项与常见排坑清单
- 中文乱码与负号方块:Linux及原生环境常缺少中文字体,需在脚本开头显式配置
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC', 'Microsoft YaHei'],以及plt.rcParams['axes.unicode_minus'] = False。 - 时间序列聚合漏项:使用
resample()聚合时,若某天完全无数据,Pandas默认会生成NaN行。直接绘图会导致折线断裂。可使用.interpolate(method='linear')或.fillna(method='ffill')处理。 - 多边形有效性(Invalid Geometry):GIS数据经常存在“自相交”(Self-intersection)导致绘图或空间连接失败。可在处理前调用
gdf['geometry'] = gdf['geometry'].buffer(0)快速修复非法拓扑。 - DPI与输出失真:在输出高精度出版物或网页嵌入图时,保存必须指定分辨率,例如
plt.savefig("output.png", dpi=300, bbox_inches='tight'),避免标签被边界截断。
六、全流程质量总结
一个健壮的时空可视化项目,从输入到最终交付物,应当遵循完整严密的规范。以下全流程总结清单可作为交付前的自检标准:
通过上述对时间序列分析、地理图层构建以及时空联动双视窗的完整实例演练,读者可以建立起结构化处理复杂时空多维数据的直观能力,并在业务报表、监控大屏及学术科研中高效交付专业的可视化结果。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













