目录
-
- [第19节:地理空间分析------使用 Geopandas 绘制热力地图](#第19节:地理空间分析——使用 Geopandas 绘制热力地图)
- 本节学习目标
- 为什么学这个
- 核心知识点讲解
-
- 一、地理空间数据基础
-
- [1.1 什么是地理空间数据?](#1.1 什么是地理空间数据?)
- [1.2 常见地理数据格式](#1.2 常见地理数据格式)
- [1.3 坐标系(CRS)](#1.3 坐标系(CRS))
- [二、GeoDataFrame 入门](#二、GeoDataFrame 入门)
-
- [2.1 创建 GeoDataFrame](#2.1 创建 GeoDataFrame)
- [2.2 从多边形创建区域](#2.2 从多边形创建区域)
- [三、读取 Shapefile 数据](#三、读取 Shapefile 数据)
- 四、Choropleth(分级设色地图)
-
- [4.1 基础 Choropleth](#4.1 基础 Choropleth)
- [4.2 Choropleth 分级的选择](#4.2 Choropleth 分级的选择)
- [4.3 将业务数据与地图合并](#4.3 将业务数据与地图合并)
- [五、Folium 交互式地图](#五、Folium 交互式地图)
-
- [5.1 基础 Folium 地图](#5.1 基础 Folium 地图)
- [5.2 热力图(Heatmap)](#5.2 热力图(Heatmap))
- [5.3 气泡地图](#5.3 气泡地图)
- 六、综合实战:中国省份销售热力地图
- 实战练习
-
- 练习一:门店选址分析
- [练习二:用 Folium 创建客户分布地图](#练习二:用 Folium 创建客户分布地图)
- 本节总结
- 下一节预告
专栏导读
🌸 欢迎来到Python办公自动化专栏---Python处理办公问题,解放您的双手
🏳️🌈 个人博客主页:请点击------> 个人的博客主页 求收藏
🏳️🌈 Github主页:请点击------> Github主页 求Star⭐
🏳️🌈 知乎主页:请点击------> 知乎主页 求关注
🏳️🌈 CSDN博客主页:请点击------> CSDN的博客主页 求关注
👍 该系列文章专栏:请点击------>Python办公自动化专栏 求订阅
🕷 此外还有爬虫专栏:请点击------>Python爬虫基础专栏 求订阅
📕 此外还有python基础专栏:请点击------>Python基础学习专栏 求订阅
文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
❤️ 欢迎各位佬关注! ❤️
第19节:地理空间分析------使用 Geopandas 绘制热力地图
本节学习目标
完成本节学习后,你将能够:
- 理解地理空间数据的基本概念(坐标系、投影、Shapefile)
- 掌握 GeoDataFrame 的数据结构与基本操作
- 读取和写入 Shapefile、GeoJSON 等地理数据格式
- 绘制分级设色地图(Choropleth)
- 使用 Geopandas 进行空间数据的基本处理
- 利用 Folium 创建交互式在线地图
- 将业务数据与地理数据结合进行空间可视化分析
为什么学这个
想象你是某连锁零售品牌的数据分析师。老板问了一个问题:"我们的门店在全国的分布合理吗?哪些省份需要新开?哪些省份已经饱和?"
你可以拿出一张包含各省份门店数量和销售额的表格------但老板看了半天也看不出规律。
你也可以画一张中国地图,用颜色深浅表示各省销售额,用气泡大小表示门店数量------一眼就能看出:"东部密集,西部稀疏;华南销售额最高,西北最低。"
这就是地理空间可视化的力量。人类的大脑天生就对空间位置敏感------一张地图比一百行数字更有说服力。
在数据分析中,地理空间分析常用于:
- 市场分布分析:门店、客户、竞争对手的地理分布
- 区域业绩对比:各省市的销售、利润、增长率地图
- 物流路径优化:仓库选址、配送路线规划
- 人口与市场分析:人口密度、收入水平、消费能力分布
核心知识点讲解
一、地理空间数据基础
1.1 什么是地理空间数据?
地理空间数据 = 普通数据 + 位置信息。位置信息可以是:
- 矢量数据:点(经纬度坐标)、线(道路、河流)、面(省份边界、区域)
- 栅格数据:卫星影像、高程图(每个像素对应一个地理位置)
在数据分析中,最常用的是矢量数据。
1.2 常见地理数据格式
| 格式 | 扩展名 | 说明 |
|---|---|---|
| Shapefile | .shp, .shx, .dbf 等 | ESRI 标准格式,最常用 |
| GeoJSON | .geojson | 基于 JSON,适合 Web 应用 |
| GeoPackage | .gpkg | SQLite 封装,单文件格式 |
| KML/KMZ | .kml, .kmz | Google Earth 格式 |
Shapefile 说明:一个 Shapefile 实际上是一组文件(.shp 存储几何形状、.shx 存储索引、.dbf 存储属性数据、.prj 存储投影信息)。使用时只需指定 .shp 文件,Geopandas 会自动读取其他相关文件。
1.3 坐标系(CRS)
坐标系定义了地球表面的点如何映射到二维平面。常见的有:
- EPSG:4326(WGS84):经纬度坐标系,GPS 使用的标准
- EPSG:3857:Web Mercator,Google 地图、百度地图使用的投影
打个比方:坐标系就像"翻译器",把三维地球上的位置"翻译"成平面地图上的坐标。选错了翻译器,地图就会变形。
二、GeoDataFrame 入门
GeoDataFrame 是 Geopandas 的核心数据结构,继承自 Pandas 的 DataFrame,多了一个 geometry 列。
python
import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt
# 从内置数据集加载(Geopandas 自带世界地图数据)
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
# 查看基本信息
print(f"数据类型: {type(world)}")
print(f"形状: {world.shape}")
print(f"\n列名: {world.columns.tolist()}")
print(f"\n前3行:")
print(world[['name', 'continent', 'pop_est', 'geometry']].head(3))
# geometry 列存储的是几何对象(多边形、点等)
print(f"\ngeometry 列的示例:")
print(world.loc[0, 'geometry'])
2.1 创建 GeoDataFrame
python
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point, Polygon
# 方法一:从点数据创建
df = pd.DataFrame({
'城市': ['北京', '上海', '广州', '深圳'],
'经度': [116.40, 121.47, 113.26, 114.06],
'纬度': [39.90, 31.23, 23.13, 22.54],
'人口(万)': [2154, 2424, 1530, 1302]
})
# 将经纬度转为 Point 对象
geometry = [Point(xy) for xy in zip(df['经度'], df['纬度'])]
# 创建 GeoDataFrame
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs='EPSG:4326')
print(gdf)
# 直接绘图
fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(ax=ax, markersize=gdf['人口(万)']/50, color='red', alpha=0.7)
# 添加城市标签
for idx, row in gdf.iterrows():
ax.annotate(row['城市'], (row['经度'], row['纬度']),
fontsize=10, ha='center')
ax.set_title('中国主要城市分布', fontsize=14, fontweight='bold')
ax.set_xlabel('经度')
ax.set_ylabel('纬度')
plt.tight_layout()
plt.show()
2.2 从多边形创建区域
python
import geopandas as gpd
from shapely.geometry import Polygon
# 创建几个模拟的区域(矩形)
polygons = [
Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]),
Polygon([(2, 0), (4, 0), (4, 2), (2, 2)]),
Polygon([(0, 2), (2, 2), (2, 4), (0, 4)]),
Polygon([(2, 2), (4, 2), (4, 4), (2, 4)])
]
gdf = gpd.GeoDataFrame({
'区域': ['A区', 'B区', 'C区', 'D区'],
'销售额': [150, 230, 180, 290],
'geometry': polygons
}, crs='EPSG:4326')
# 绘制面图
fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(column='销售额', ax=ax, legend=True,
cmap='YlOrRd', edgecolor='black',
legend_kwds={'label': '销售额(万元)'})
for idx, row in gdf.iterrows():
centroid = row['geometry'].centroid
ax.annotate(row['区域'], (centroid.x, centroid.y),
fontsize=14, ha='center', va='center', fontweight='bold')
ax.set_title('模拟区域销售分布', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
三、读取 Shapefile 数据
实际工作中,地图数据通常来自外部文件。以下以中国省级地图数据为例。
python
import geopandas as gpd
import matplotlib.pyplot as plt
# 读取中国省级地图 Shapefile
# (实际使用时替换为你本地的 Shapefile 路径)
# china_map = gpd.read_file('中国省级地图/china-provinces.shp')
# 这里用世界地图作为演示
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
# 筛选亚洲国家
asia = world[world['continent'] == 'Asia']
fig, ax = plt.subplots(figsize=(14, 8))
# 基础地图绘制
asia.plot(ax=ax, color='lightgray', edgecolor='black', linewidth=0.5)
# 为每个国家标注名称
for idx, row in asia.iterrows():
centroid = row['geometry'].centroid
ax.annotate(row['name'], (centroid.x, centroid.y),
fontsize=7, ha='center', va='center', alpha=0.7)
ax.set_title('亚洲国家分布', fontsize=16, fontweight='bold')
ax.set_xlim(60, 150)
ax.set_ylim(5, 55)
ax.set_xlabel('经度')
ax.set_ylabel('纬度')
plt.tight_layout()
plt.show()
四、Choropleth(分级设色地图)
Choropleth 地图是最常用的地理可视化方式------用颜色深浅表示数值大小。
4.1 基础 Choropleth
python
import geopandas as gpd
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 使用世界地图 + 模拟GDP数据
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
# 模拟GDP数据(实际应用中使用真实数据)
np.random.seed(42)
world['GDP_模拟'] = np.random.lognormal(10, 2, len(world))
# 排除南极洲
world = world[world['name'] != 'Antarctica']
fig, axes = plt.subplots(1, 2, figsize=(20, 8))
# 子图1:原始 Choropleth
world.plot(column='GDP_模拟', ax=axes[0], cmap='viridis',
legend=True, edgecolor='white', linewidth=0.3,
legend_kwds={'label': '模拟GDP', 'orientation': 'horizontal'})
axes[0].set_title('世界GDP分布(线性刻度)', fontsize=14, fontweight='bold')
axes[0].axis('off')
# 子图2:对数刻度(更适合差距大的数据)
world.plot(column='GDP_模拟', ax=axes[1], cmap='viridis',
scheme='quantiles', k=7, # 分位数分7级
legend=True, edgecolor='white', linewidth=0.3,
legend_kwds={'label': '模拟GDP', 'orientation': 'horizontal'})
axes[1].set_title('世界GDP分布(分位数分级)', fontsize=14, fontweight='bold')
axes[1].axis('off')
plt.tight_layout()
plt.show()
4.2 Choropleth 分级的选择
颜色分级的方法会影响地图的视觉效果和数据传达:
python
import geopandas as gpd
import matplotlib.pyplot as plt
import numpy as np
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
np.random.seed(42)
world['value'] = np.random.lognormal(8, 1.5, len(world))
world = world[world['name'] != 'Antarctica']
schemes = ['quantiles', 'equal_interval', 'natural_breaks']
titles = ['分位数分级 (Quantiles)', '等距分级 (Equal Interval)', '自然断点分级 (Natural Breaks)']
fig, axes = plt.subplots(1, 3, figsize=(24, 7))
for i, (scheme, title) in enumerate(zip(schemes, titles)):
try:
world.plot(column='value', ax=axes[i], cmap='YlOrRd',
scheme=scheme, k=6,
legend=True, edgecolor='white', linewidth=0.3,
legend_kwds={'label': '数值', 'orientation': 'horizontal',
'shrink': 0.6})
except:
# 如果缺少 mapclassify 库,使用默认分级
world.plot(column='value', ax=axes[i], cmap='YlOrRd',
legend=True, edgecolor='white', linewidth=0.3)
axes[i].set_title(title, fontsize=14, fontweight='bold')
axes[i].axis('off')
plt.tight_layout()
plt.show()
# 分级方法说明:
# - quantiles: 每个颜色等级包含相同数量的区域(推荐通用场景)
# - equal_interval: 数值范围等分(适合均匀分布数据)
# - natural_breaks: 基于数据自然聚集点分界(适合有聚类特征的数据)
4.3 将业务数据与地图合并
python
import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# 基础地图
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
world = world[world['name'] != 'Antarctica']
# 模拟业务数据(各国家的销售额和门店数)
np.random.seed(42)
business_data = pd.DataFrame({
'name': world['name'].values,
'sales': np.random.randint(50, 500, len(world)),
'stores': np.random.randint(5, 100, len(world)),
'growth': np.random.uniform(-10, 30, len(world))
})
# 合并地图数据和业务数据(类似 Pandas 的 merge)
merged = world.merge(business_data, on='name', how='left')
fig, axes = plt.subplots(1, 2, figsize=(20, 7))
# 左图:销售额
merged.plot(column='sales', ax=axes[0], cmap='YlOrRd',
scheme='quantiles', k=6,
legend=True, edgecolor='white', linewidth=0.3,
legend_kwds={'label': '销售额(万元)', 'orientation': 'horizontal'})
axes[0].set_title('全球销售额分布', fontsize=14, fontweight='bold')
axes[0].axis('off')
# 右图:增长率(发散型颜色)
merged.plot(column='growth', ax=axes[1], cmap='RdBu_r',
scheme='quantiles', k=7,
legend=True, edgecolor='white', linewidth=0.3,
legend_kwds={'label': '增长率(%)', 'orientation': 'horizontal'})
axes[0].set_title('全球销售额分布', fontsize=14, fontweight='bold')
axes[0].axis('off')
axes[1].set_title('全球增长率分布(正负分化)', fontsize=14, fontweight='bold')
axes[1].axis('off')
plt.tight_layout()
plt.show()
五、Folium 交互式地图
Folium 基于 Leaflet.js 创建可在浏览器中交互的在线地图。
5.1 基础 Folium 地图
python
import folium
import pandas as pd
import numpy as np
# 创建基础地图(以中国为中心)
m = folium.Map(
location=[35.0, 105.0], # 中心点(纬度,经度)
zoom_start=4, # 初始缩放级别
tiles='OpenStreetMap' # 地图样式
)
# 添加标记点
cities = pd.DataFrame({
'城市': ['北京', '上海', '广州', '深圳', '成都', '杭州'],
'纬度': [39.90, 31.23, 23.13, 22.54, 30.57, 30.27],
'经度': [116.40, 121.47, 113.26, 114.06, 104.07, 120.15],
'人口(万)': [2154, 2424, 1530, 1302, 1633, 1194]
})
for _, row in cities.iterrows():
folium.Marker(
location=[row['纬度'], row['经度']],
popup=folium.Popup(
f"<b>{row['城市']}</b><br>人口: {row['人口(万)']}万",
max_width=200
),
icon=folium.Icon(color='blue', icon='info-sign')
).add_to(m)
# 保存为 HTML 文件
m.save('interactive_map.html')
print("交互式地图已保存为: interactive_map.html")
print("用浏览器打开即可查看")
# 在 Jupyter 中直接显示 m
# m
5.2 热力图(Heatmap)
python
from folium.plugins import HeatMap
import numpy as np
# 创建基础地图
m = folium.Map(location=[35.0, 105.0], zoom_start=4, tiles='OpenStreetMap')
# 模拟客户位置数据
np.random.seed(42)
n_points = 1000
latitudes = np.random.normal(35, 10, n_points)
longitudes = np.random.normal(105, 15, n_points)
# 创建热力图数据:[纬度, 经度, 权重]
heat_data = [[lat, lon, np.random.uniform(0.5, 1.5)]
for lat, lon in zip(latitudes, longitudes)]
# 添加热力图层
HeatMap(heat_data, radius=20, blur=15, max_zoom=1).add_to(m)
m.save('customer_heatmap.html')
print("客户分布热力图已保存为: customer_heatmap.html")
5.3 气泡地图
python
from folium.plugins import MarkerCluster
import pandas as pd
# 模拟门店数据
np.random.seed(42)
stores = pd.DataFrame({
'店名': [f'门店{i}' for i in range(1, 31)],
'纬度': np.random.normal(32, 8, 30),
'经度': np.random.normal(110, 12, 30),
'月营收': np.random.randint(20, 150, 30),
'评级': np.random.choice(['A', 'B', 'C'], 30, p=[0.3, 0.5, 0.2])
})
# 评级对应颜色
color_map = {'A': 'green', 'B': 'blue', 'C': 'red'}
m = folium.Map(location=[35.0, 105.0], zoom_start=4)
# 使用 MarkerCluster 实现缩放聚合
marker_cluster = MarkerCluster().add_to(m)
for _, row in stores.iterrows():
folium.CircleMarker(
location=[row['纬度'], row['经度']],
radius=row['月营收'] / 10, # 气泡大小与营收相关
color=color_map[row['评级']],
fill=True,
fill_color=color_map[row['评级']],
fill_opacity=0.6,
popup=folium.Popup(
f"<b>{row['店名']}</b><br>"
f"月营收: {row['月营收']}万元<br>"
f"评级: {row['评级']}",
max_width=200
)
).add_to(marker_cluster)
m.save('store_bubble_map.html')
print("门店气泡地图已保存为: store_bubble_map.html")
六、综合实战:中国省份销售热力地图
python
import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# 模拟数据:中国各省份销售
np.random.seed(42)
provinces_data = pd.DataFrame({
'省份': ['北京', '上海', '广东', '江苏', '浙江', '山东', '河南',
'四川', '湖北', '湖南', '福建', '安徽', '河北', '辽宁',
'陕西', '重庆', '天津', '江西', '云南', '广西',
'山西', '贵州', '吉林', '甘肃', '海南', '宁夏',
'青海', '西藏', '新疆', '内蒙古', '黑龙江'],
'销售额': np.random.randint(50, 500, 31),
'增长率': np.random.uniform(-5, 25, 31),
'门店数': np.random.randint(5, 80, 31)
})
# 注意:实际工作中需要读取真实的中国地图 Shapefile
# 这里用世界地图中的中国区域作为演示
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
china = world[world['name'] == 'China']
fig, axes = plt.subplots(1, 2, figsize=(16, 6))
# 绘制中国地图(简化版)
china.plot(ax=axes[0], color='lightblue', edgecolor='black', linewidth=1)
axes[0].set_title('中国地图(示意)', fontsize=14, fontweight='bold')
axes[0].axis('off')
# 业务数据可视化
colors = plt.cm.YlOrRd(np.linspace(0.2, 0.9, 31))
scatter = axes[1].scatter(
provinces_data['销售额'],
provinces_data['增长率'],
s=provinces_data['门店数'] * 15,
c=provinces_data['销售额'],
cmap='YlOrRd',
alpha=0.7,
edgecolors='black',
linewidth=0.5
)
# 标注部分省份
for idx, row in provinces_data.head(10).iterrows():
axes[1].annotate(row['省份'], (row['销售额'], row['增长率']),
fontsize=8, ha='center')
cbar = plt.colorbar(scatter, ax=axes[1])
cbar.set_label('销售额(万元)', fontsize=11)
axes[1].set_title('各省份销售分析(气泡=门店数)', fontsize=14, fontweight='bold')
axes[1].set_xlabel('销售额(万元)')
axes[1].set_ylabel('增长率(%)')
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
实战练习
练习一:门店选址分析
假设你正在为一家连锁咖啡店分析新门店选址。现有数据包括:各商圈的人流量、平均收入、竞争门店数量、租金水平。请:
- 在地图上标注现有门店位置(用不同颜色区分业绩等级)
- 创建一个模拟的区域热力图,显示各商圈的"开店指数"
- 标注推荐的新店选址
参考答案:
python
import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from shapely.geometry import Point, Polygon
# 模拟商圈数据
np.random.seed(42)
districts = pd.DataFrame({
'商圈': ['商圈A', '商圈B', '商圈C', '商圈D', '商圈E',
'商圈F', '商圈G', '商圈H', '商圈I', '商圈J'],
'中心经度': np.random.uniform(115, 122, 10),
'中心纬度': np.random.uniform(30, 42, 10),
'人流量': np.random.randint(5000, 50000, 10),
'平均收入': np.random.randint(8000, 25000, 10),
'竞争店数': np.random.randint(0, 15, 10),
'月租金': np.random.randint(200, 1000, 10)
})
# 计算开店指数 = 人流量/竞争店数 * 收入水平 / 租金
districts['开店指数'] = (districts['人流量'] / (districts['竞争店数'] + 1) *
districts['平均收入'] / districts['月租金'])
# 现有门店
stores = pd.DataFrame({
'店名': ['门店1', '门店2', '门店3', '门店4', '门店5'],
'经度': districts['中心经度'].head(5).values,
'纬度': districts['中心纬度'].head(5).values,
'月业绩': [85, 62, 91, 45, 73]
})
stores['等级'] = pd.cut(stores['月业绩'], bins=[0, 50, 70, 100],
labels=['C', 'B', 'A'])
fig, axes = plt.subplots(1, 2, figsize=(16, 6))
# 左图:现有门店分布
colors_map = {'A': 'green', 'B': 'orange', 'C': 'red'}
for _, store in stores.iterrows():
axes[0].scatter(store['经度'], store['纬度'],
s=store['月业绩'] * 15,
c=colors_map[store['等级']],
alpha=0.7, edgecolors='black', linewidth=1, zorder=5)
axes[0].annotate(store['店名'], (store['经度'], store['纬度']),
fontsize=8, ha='center')
axes[0].set_title('现有门店分布(绿=A级,橙=B,红=C)', fontsize=13)
axes[0].grid(True, alpha=0.3)
# 右图:商圈开店指数
bars = axes[1].barh(districts['商圈'], districts['开店指数'],
color=plt.cm.YlOrRd(np.linspace(0.3, 0.9, 10)))
axes[1].set_title('各商圈开店指数排行', fontsize=13)
axes[1].set_xlabel('开店指数(越大越推荐)')
# 标注推荐选址
top3 = districts.nlargest(3, '开店指数')
for _, d in top3.iterrows():
axes[1].annotate(f'推荐!', (d['开店指数'], d['商圈']),
fontsize=9, color='red', fontweight='bold')
plt.tight_layout()
plt.show()
print("推荐开店商圈(按开店指数):")
print(districts[['商圈', '开店指数']].sort_values('开店指数', ascending=False).head(3))
练习二:用 Folium 创建客户分布地图
利用 Folium 创建一个交互式的客户分布地图,包含热力图层和标记点。
参考答案:
python
import folium
from folium.plugins import HeatMap, MarkerCluster
import numpy as np
import pandas as pd
np.random.seed(42)
# 模拟客户数据(以中国主要城市为中心聚集)
city_centers = [
[39.90, 116.40, '北京'], # 纬度, 经度, 城市名
[31.23, 121.47, '上海'],
[23.13, 113.26, '广州'],
[30.57, 104.07, '成都'],
[22.54, 114.06, '深圳']
]
customers = []
for lat, lon, city in city_centers:
n = np.random.randint(50, 150)
for _ in range(n):
customers.append([
lat + np.random.normal(0, 2),
lon + np.random.normal(0, 2),
city
])
df = pd.DataFrame(customers, columns=['lat', 'lon', '城市'])
# 创建基础地图
m = folium.Map(location=[33, 110], zoom_start=5)
# 添加热力图
heat_data = [[row['lat'], row['lon']] for _, row in df.iterrows()]
HeatMap(heat_data, radius=15, blur=10, max_zoom=8).add_to(m)
# 添加城市标记
for lat, lon, city in city_centers:
count = len(df[df['城市'] == city])
folium.CircleMarker(
location=[lat, lon],
radius=count / 10,
color='blue',
fill=True,
fill_color='blue',
fill_opacity=0.5,
popup=f'{city}: {count} 位客户'
).add_to(m)
m.save('customer_distribution.html')
print("客户分布地图已保存为: customer_distribution.html")
本节总结
本节我们学习了地理空间分析的核心内容:
- 地理数据基础:矢量数据、常见格式(Shapefile/GeoJSON)、坐标系概念
- GeoDataFrame:Pandas DataFrame 的"地理扩展版",增加了 geometry 列
- 数据读取:从 Shapefile 等文件加载地理数据,与业务数据合并
- Choropleth 地图:用颜色深浅表示数值大小,注意分级方法的选择
- Folium 交互地图:创建可在浏览器中交互的在线地图,支持热力图、气泡图、标记点
- 空间可视化策略:根据分析目的选择合适的可视化方式
核心认知:地图可视化的本质是把数字"翻译"为空间模式。选择合适的颜色映射、分级方法和投影方式,才能确保翻译的"准确性"。记住:一张好的地图,读者应该在 3 秒内发现数据的关键模式。
下一节预告
第20节我们将学习 探索性分析(EDA)------如何通过图表发现数据背后的规律。前面我们学了很多绘图工具,但"画什么图"和"怎么画"同样重要。EDA 是一套系统化的数据分析流程,帮助你在建模之前全面理解数据。我们将学习 EDA 的完整流程,包括数据概况、分布分析、异常值检测、多变量关系,以及如何生成一份完整的 EDA 报告。
结尾
希望对初学者有帮助;致力于办公自动化的小小程序员一枚
希望能得到大家的【❤️一个免费关注❤️】感谢!
求个 🤞 关注 🤞 +❤️ 喜欢 ❤️ +👍 收藏 👍
此外还有办公自动化专栏,欢迎大家订阅:Python办公自动化专栏
此外还有爬虫专栏,欢迎大家订阅:Python爬虫基础专栏
此外还有Python基础专栏,欢迎大家订阅:Python基础学习专栏