原来 Matplotlib 绘图也可以这么漂亮,这次真的是学习到了!

来源:Python大数据分析 作者:朱卫军


2.1 观察原作品

2.2 开始动手!
2.2.1 构建坐标系统

import geopandas as gpdfrom shapely.geometry import LineString, Point, Polygonimport matplotlib.pyplot as pltimport numpy as npimport warningsplt.rcParams['font.sans-serif'] = ['SimHei'] # 解决matplotlib中文乱码问题plt.rcParams['axes.unicode_minus'] = False # 解决matplotlib负号显示问题warnings.filterwarnings('ignore')# 设置中心点在南极点的正射投影crs = '+proj=ortho +lon_0=0 +lat_0=-90'# 构建经度线并设置对应经纬度的地理坐标系lng_lines = gpd.GeoDataFrame({'geometry': [LineString([[lng, -90], [lng, -78]]) for lng in np.arange(10, 220, 210 / 38)]},crs='EPSG:4326')# 构建纬度线并设置为对应经纬度的地理坐标系lat_lines = gpd.GeoDataFrame({'geometry': [LineString([[lng, lat] for lng in range(10, 220)]) for lat in range(-90, -79, 2)]},crs='EPSG:4326')

2.2.2 绘制指标折线

def fake_index(value):fake = []fake.append(value+np.random.uniform(5, 10))fake.append(value-np.random.uniform(5, 10))return np.random.choice(fake, size=2, replace=False).tolist()data['购房自由指数'], data['租房自由指数'] = list(zip(*data['居住自由指数'].apply(fake_index)))# 修正伪造数据中大于100和小于0的情况data.loc[:, '居住自由指数':] = data.loc[:, '居住自由指数':].applymap(lambda v: 100 if v > 100 else v)data.loc[:, '居住自由指数':] = data.loc[:, '居住自由指数':].applymap(lambda v: 0 if v < 0 else v)data.head()


# 为每个城市生成1条经线lng_lines = gpd.GeoDataFrame({'geometry': [LineString([[lng, -90], [lng, -78]]) for lng in np.arange(10, 220, 210 / data.shape[0])]},crs='EPSG:4326')# 居住自由指数对应的折线line1 = gpd.GeoDataFrame({'geometry': [LineString([(lng, lat) for lng, lat in zip(np.arange(10, 220, 210 / data.shape[0]),data['居住自由指数_映射值'])])]},crs='EPSG:4326')# 居住自由指数对应的折线上的散点scatter1 = gpd.GeoDataFrame({'geometry': [Point(lng, lat) for lng, lat in zip(np.arange(10, 220, 210 / data.shape[0]),data['居住自由指数_映射值'])]}, crs='EPSG:4326')# 购房自由指数对应的折线line2 = gpd.GeoDataFrame({'geometry': [LineString([(lng, lat) for lng, lat in zip(np.arange(10, 220, 210 / data.shape[0]),data['购房自由指数_映射值'])])]},crs='EPSG:4326')# 购房自由指数对应的折线上的散点scatter2 = gpd.GeoDataFrame({'geometry': [Point(lng, lat) for lng, lat in zip(np.arange(10, 220, 210 / data.shape[0]),data['购房自由指数_映射值'])]}, crs='EPSG:4326')# 租房自由指数对应的折线line3 = gpd.GeoDataFrame({'geometry': [LineString([(lng, lat) for lng, lat in zip(np.arange(10, 220, 210 / data.shape[0]),data['租房自由指数_映射值'])])]},crs='EPSG:4326')# 租房自由指数对应的折线上的散点scatter3 = gpd.GeoDataFrame({'geometry': [Point(lng, lat) for lng, lat in zip(np.arange(10, 220, 210 / data.shape[0]),data['租房自由指数_映射值'])]}, crs='EPSG:4326')fig, ax = plt.subplots(figsize=(8, 8))# 绘制经度线与纬度线ax = lng_lines.to_crs(crs).plot(ax=ax, linewidth=0.4, edgecolor='lightgrey')ax = lat_lines.to_crs(crs).plot(ax=ax, linewidth=0.75, edgecolor='grey', alpha=0.8)ax = line1.to_crs(crs).plot(ax=ax, color='black', linewidth=1)ax = scatter1.to_crs(crs).plot(ax=ax, color='black', markersize=12)ax = line2.to_crs(crs).plot(ax=ax, color='#00CED1', linewidth=0.6)ax = scatter2.to_crs(crs).plot(ax=ax, color='#00CED1', markersize=4)ax = line3.to_crs(crs).plot(ax=ax, color='lightgrey', linewidth=0.6)ax = scatter3.to_crs(crs).plot(ax=ax, color='lightgrey', markersize=4)ax.axis('off'); # 关闭坐标轴fig.savefig('图11.png', dpi=500, inches_bbox='tight', inches_pad=0)
图9
2.2.3 绘制填充区域



fig, ax = plt.subplots(figsize=(8, 8))# 绘制经度线与纬度线ax = lng_lines.to_crs(crs).plot(ax=ax, linewidth=0.4, edgecolor='lightgrey')ax = lat_lines.to_crs(crs).plot(ax=ax, linewidth=0.75, edgecolor='grey', alpha=0.8)ax = line1.to_crs(crs).plot(ax=ax, color='black', linewidth=1)ax = scatter1.to_crs(crs).plot(ax=ax, color='black', markersize=12)ax = line2.to_crs(crs).plot(ax=ax, color='#00CED1', linewidth=0.6)ax = scatter2.to_crs(crs).plot(ax=ax, color='#00CED1', markersize=4)ax = line3.to_crs(crs).plot(ax=ax, color='lightgrey', linewidth=0.6)ax = scatter3.to_crs(crs).plot(ax=ax, color='lightgrey', markersize=4)ax = polygon1.difference(polygon2).plot(ax=ax, color='#00CED1', alpha=0.2)polygon2.difference(polygon1).plot(ax=ax, color='lightgrey', alpha=0.6)ax.axis('off'); # 关闭坐标轴fig.savefig('图13.png', dpi=500, inches_bbox='tight', inches_pad=0)

2.2.4 补充文字、标注等元素

图14

评论
