我正在尝试使用英国县地图创建热图。我已经尝试了几个星期但没有成功。
这是我拥有的数据示例:
county_name normalized_count latitude longitude
20 Army 2.146520 51.5074 -0.1278
31 Bedfordshire 17.960133 52.1387 -0.4669
35 Berks & Bucks 20.326667 51.4664 -0.9731
46 Birmingham 6.846455 52.4862 -1.8904
57 Cambridgeshire 21.258065 52.2053 0.1218
68 Cheshire 12.232529 53.2326 -2.6103
79 Cornwall 16.530534 50.2660 -5.0527
90 Cumberland 8.604545 54.6633 -3.1828
101 Derbyshire 14.582173 53.1224 -1.5564
112 Devon 12.771468 50.7156 -3.5309
123 Dorset 10.192857 50.7488 -2.3445
134 Durham 8.644309 54.7761 -1.5733
145 East Riding 7.403646 53.7577 -0.7798
156 Essex 8.894873 51.7340 0.4691
167 Gloucestershire 12.392987 51.8642 -2.2382
177 Guernsey 43.000000 49.4482 -2.5895
188 Hampshire 12.022789 51.0577 -1.3080
199 Herefordshire 12.397727 52.0765 -2.6544
210 Hertfordshire 10.315981 51.7670 -0.2087
221 Huntingdonshire 21.110000 52.3302 -0.1759
232 Isle of Man 36.088235 54.2361 -4.5481
243 Jersey 44.766667 49.2144 -2.1312
254 Kent 12.353401 51.2787 0.5216
265 Lancashire 12.315197 53.7632 -2.7034
287 Lincolnshire 10.234957 53.2344 -0.5384
298 Liverpool 7.028662 53.4084 -2.9916
309 London 5.495880 51.5074 -0.1278
320 Manchester 8.221386 53.4808 -2.2426
331 Middlesex 9.389552 51.5537 -0.3177
342 Norfolk 14.648590 52.6309 1.2974
353 North Riding 10.763959 54.2641 -1.3157
364 Northamptonshire 11.497890 52.2405 -0.9027
375 Northumberland 8.936893 55.1790 -1.8262
386 Nottinghamshire 11.402954 53.1004 -1.0502
397 Oxfordshire 20.697802 51.7519 -1.2578
406 RAF 2.134831 52.3610 -0.7020
408 Royal Navy 0.196319 50.7989 -1.0912
419 Sheffield & Hallamshire 7.512452 53.3811 -1.4701
430 Shropshire 14.255435 52.7070 -2.7549
441 Somerset 12.581616 51.1000 -3.0000
452 Staffordshire 7.322162 52.8054 -2.1177
463 Suffolk 15.604027 52.1872 0.9708
474 Surrey 9.643979 51.3148 -0.5599
485 Sussex 20.224490 50.9097 -0.2079
505 West Riding 8.980066 53.8008 -1.5491
516 Westmorland 8.141026 54.4493 -2.7515
527 Wiltshire 14.117438 51.3524 -1.9930
538 Worcestershire 13.275410 52.1920 -2.2216
现在我获取县的经纬度的方法是通过chatgpt,并创建一个数据字典,然后用它来映射到我的数据。这是代码:
county_coordinates = {
'Amateur Football Alliance': (51.509865, -0.118092),
'Army': (51.5074, -0.1278),
'Bedfordshire': (52.1387, -0.4669),
'Berks & Bucks': [(51.4664, -0.9731), (51.8099, -1.0201)], # Berkshire and Buckinghamshire
'Birmingham': (52.4862, -1.8904),
'Cambridgeshire': (52.2053, 0.1218),
'Cheshire': (53.2326, -2.6103),
'Cornwall': (50.2660, -5.0527),
'Cumberland': (54.6633, -3.1828),
'Derbyshire': (53.1224, -1.5564),
'Devon': (50.7156, -3.5309),
'Dorset': (50.7488, -2.3445),
'Durham': (54.7761, -1.5733),
'East Riding': (53.7577, -0.7798),
'Essex': (51.7340, 0.4691),
'Gloucestershire': (51.8642, -2.2382),
'Guernsey': (49.4482, -2.5895),
'Hampshire': (51.0577, -1.3080),
'Herefordshire': (52.0765, -2.6544),
'Hertfordshire': (51.7670, -0.2087),
'Huntingdonshire': (52.3302, -0.1759),
'Isle of Man': (54.2361, -4.5481),
'Jersey': (49.2144, -2.1312),
'Kent': (51.2787, 0.5216),
'Lancashire': (53.7632, -2.7034),
'Leicestershire: ': [(52.6369, -1.1398), (52.6712, -0.7558)], # Leicestershire and Rutland
'Lincolnshire': (53.2344, -0.5384),
'Liverpool': (53.4084, -2.9916),
'London': (51.5074, -0.1278),
'Manchester': (53.4808, -2.2426),
'Middlesex': (51.5537, -0.3177),
'Norfolk': (52.6309, 1.2974),
'Northamptonshire': (52.2405, -0.9027),
'North Riding': (54.2641, -1.3157),
'Northumberland': (55.1790, -1.8262),
'Nottinghamshire': (53.1004, -1.0502),
'Oxfordshire': (51.7519, -1.2578),
'RAF': (52.3610, -0.7020),
'Royal Navy': (50.7989, -1.0912),
'Sheffield & Hallamshire': [(53.3811, -1.4701), (53.3640, -1.5189)], # Sheffield and Hallamshire
'Shropshire': (52.7070, -2.7549),
'Somerset': (51.1000, -3.0000),
'Staffordshire': (52.8054, -2.1177),
'Suffolk': (52.1872, 0.9708),
'Surrey': (51.3148, -0.5599),
'Sussex': (50.9097, -0.2079),
'The FA': (51.5560, -0.2797), # Football Association
'West Riding': (53.8008, -1.5491),
'Westmorland': (54.4493, -2.7515),
'Wiltshire': (51.3524, -1.9930),
'Worcestershire': (52.1920, -2.2216)
}
# Add latitude and longitude columns to the normalized_df
normalized_df['latitude'] = normalized_df['county_name'].map(lambda x: county_coordinates.get(x, (None, None))[0])
normalized_df['longitude'] = normalized_df['county_name'].map(lambda x: county_coordinates.get(x, (None, None))[1])
这是我尝试过的代码:
# Load the shapefile
gb_100km = gpd.read_file('mapfiles/gb_100km.shp')
这就是我的 gb_100km 的样子:
CELLCODE EOFORIGIN NOFORIGIN geometry
0 100kmE27N29 2700000 2900000 POLYGON ((2700000 2900000, 2700000 3000000, 28...
1 100kmE27N30 2700000 3000000 POLYGON ((2700000 3000000, 2700000 3100000, 28...
2 100kmE28N28 2800000 2800000 POLYGON ((2800000 2800000, 2800000 2900000, 29...
3 100kmE28N29 2800000 2900000 POLYGON ((2800000 2900000, 2800000 3000000, 29...
4 100kmE28N30 2800000 3000000 POLYGON ((2800000 3000000, 2800000 3100000, 29...
... ... ... ... ...
139 100kmE38N44 3800000 4400000 POLYGON ((3800000 4400000, 3800000 4500000, 39...
140 100kmE38N45 3800000 4500000 POLYGON ((3800000 4500000, 3800000 4600000, 39...
141 100kmE39N35 3900000 3500000 POLYGON ((3900000 3500000, 3900000 3600000, 40...
142 100kmE39N36 3900000 3600000 POLYGON ((3900000 3600000, 3900000 3700000, 40...
143 100kmE39N37 3900000 3700000 POLYGON ((3900000 3700000, 3900000 3800000, 40...
这是另一个代码:
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
from shapely.geometry import Point
# Load the UK shapefile (replace with your actual path)
uk_shapefile = gpd.read_file('mapfiles/gb_100km.shp')
# Drop rows with missing latitude or longitude
normalized_df_with_latlong = normalized_df_with_latlong.dropna(subset=['latitude', 'longitude'])
# Extract latitude and longitude values if they are tuples
normalized_df_with_latlong['latitude'] = [lat for lat, lon in normalized_df_with_latlong['latitude']]
normalized_df_with_latlong['longitude'] = [lon for lat, lon in normalized_df_with_latlong['longitude']]
# Convert latitude and longitude to floats
#normalized_df_with_latlong['latitude'] = normalized_df_with_latlong['latitude'].astype(float)
#normalized_df_with_latlong['longitude'] = normalized_df_with_latlong['longitude'].astype(float)
# Create a GeoDataFrame from your data
counties = gpd.GeoDataFrame(
normalized_df_with_latlong,
geometry=gpd.points_from_xy(normalized_df_with_latlong.longitude, normalized_df_with_latlong.latitude),
crs='EPSG:4326'
)
# Ensure both GeoDataFrames use the same CRS
counties = counties.to_crs(uk_shapefile.crs)
# Create a figure and axes
fig, ax = plt.subplots(1, 1, figsize=(10, 6))
# Plot the UK shapefile
uk_shapefile.plot(ax=ax, color='lightgray', edgecolor='black')
# Plot the normalized counts as a heatmap
counties.plot(
column='normalized_count',
ax=ax,
cmap='Reds',
legend=True,
markersize=50,
alpha=0.7
)
# Set title and labels
ax.set_title('Normalized Counts by Case Type in UK')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
# Adjust layout and show the plot
plt.tight_layout()
plt.show()
试图理解为什么我无法绘制这张地图以及为什么会出现此错误:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[77], line 18
16 normalized_df_with_latlong = normalized_df_with_latlong.dropna(subset=['latitude', 'longitude'])
17 # Extract latitude and longitude values if they are tuples
---> 18 normalized_df_with_latlong['latitude'] = [lat for lat, lon in normalized_df_with_latlong['latitude']]
19 normalized_df_with_latlong['longitude'] = [lon for lat, lon in normalized_df_with_latlong['longitude']]
21 # Convert latitude and longitude to floats
22 #normalized_df_with_latlong['latitude'] = normalized_df_with_latlong['latitude'].astype(float)
23 #normalized_df_with_latlong['longitude'] = normalized_df_with_latlong['longitude'].astype(float)
24
25 # Create a GeoDataFrame from your data
TypeError: cannot unpack non-iterable float object
这是我最后一个错误。还有其他错误,我想我已经解决了它们。
看起来您在数据转换/清理方面遇到了问题。它看起来不像绘图或 geopandas 问题 - 与您处理数据的方式更相关。
我使用
https://geodata.ucdavis.edu/gadm/gadm4.1/shp/gadm41_GBR_shp.zip
作为形状文件,因为我没有你的 mapfiles/gb_100km.shp
。
不幸的是,我无法创建实际的热图,因为由于某种原因
fill=True
导致 AttributeError: 'PlateCarree' object has no attribute 'contains_branch_seperately'
。
无论如何,这是迄今为止我能做的最好的事情。
这是绘制一些点的代码(如果您需要调整或问题,请发表评论):
#!/usr/bin/env python3
import geopandas as gpd
from shapely.geometry import Point
import random
import matplotlib.pyplot as plt
import geoplot as gplt
import geoplot.crs as gcrs
county_coordinates = {
'Amateur Football Alliance': (51.509865, -0.118092),
'Army': (51.5074, -0.1278),
'Bedfordshire': (52.1387, -0.4669),
'Birmingham': (52.4862, -1.8904),
'Cambridgeshire': (52.2053, 0.1218),
'Cheshire': (53.2326, -2.6103),
'Cornwall': (50.2660, -5.0527),
'Cumberland': (54.6633, -3.1828),
'Derbyshire': (53.1224, -1.5564),
'Devon': (50.7156, -3.5309),
'Dorset': (50.7488, -2.3445),
'Durham': (54.7761, -1.5733),
'East Riding': (53.7577, -0.7798),
'Essex': (51.7340, 0.4691),
'Gloucestershire': (51.8642, -2.2382),
'Guernsey': (49.4482, -2.5895),
'Hampshire': (51.0577, -1.3080),
'Herefordshire': (52.0765, -2.6544),
'Hertfordshire': (51.7670, -0.2087),
'Huntingdonshire': (52.3302, -0.1759),
'Isle of Man': (54.2361, -4.5481),
'Jersey': (49.2144, -2.1312),
'Kent': (51.2787, 0.5216),
'Lancashire': (53.7632, -2.7034),
'Lincolnshire': (53.2344, -0.5384),
'Liverpool': (53.4084, -2.9916),
'London': (51.5074, -0.1278),
'Manchester': (53.4808, -2.2426),
'Middlesex': (51.5537, -0.3177),
'Norfolk': (52.6309, 1.2974),
'Northamptonshire': (52.2405, -0.9027),
'North Riding': (54.2641, -1.3157),
'Northumberland': (55.1790, -1.8262),
'Nottinghamshire': (53.1004, -1.0502),
'Oxfordshire': (51.7519, -1.2578),
'RAF': (52.3610, -0.7020),
'Royal Navy': (50.7989, -1.0912),
'Shropshire': (52.7070, -2.7549),
'Somerset': (51.1000, -3.0000),
'Staffordshire': (52.8054, -2.1177),
'Suffolk': (52.1872, 0.9708),
'Surrey': (51.3148, -0.5599),
'Sussex': (50.9097, -0.2079),
'The FA': (51.5560, -0.2797), # Football Association
'West Riding': (53.8008, -1.5491),
'Westmorland': (54.4493, -2.7515),
'Wiltshire': (51.3524, -1.9930),
'Worcestershire': (52.1920, -2.2216)
}
data = {
'county': [],
'latitude': [],
'longitude': [],
'count': [],
}
for county_name, value in county_coordinates.items():
lat, long = value
count = random.uniform(10, 12) # real count not available, so I randomize
data['county'].append(county_name)
data['latitude'].append(lat)
data['longitude'].append(long)
data['count'].append(count)
geometry = [Point(xy) for xy in zip(data['longitude'], data['latitude'])]
gdf = gpd.GeoDataFrame(data, geometry=geometry, crs='EPSG:4326')
# Load the UK shapefile (replace with your actual path)
uk_shapefile = gpd.read_file('files/gadm41_GBR_0.shp')
# Create a figure and axes
fig = plt.figure(figsize=(10, 5))
ax = gplt.kdeplot(
gdf,
projection=gcrs.AlbersEqualArea(),
cmap='Reds',
# fill=True # would make it nice, but does not work: "AttributeError: 'PlateCarree' object has no attribute 'contains_branch_seperately'"
)
gplt.polyplot(uk_shapefile, ax=ax)
# Set title and labels
ax.set_title('Normalized Counts by Case Type in UK')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
# Adjust layout and show/export the plot
plt.tight_layout()
# plt.show()
plt.savefig('counts_by_case_type_in_uk.png')
它的样子是这样的:
我无法绘制各县的原因与我想合并的正确 shp 文件有关。
有多个shp文件,我的数据是基于这些文件合并的。根据我合并的列,在我的例子中 - 县 - 那么应该考虑正确选择 shp 文件。例如:
gadm41_GBR_0.shp
gadm41_GBR_1.shp
gadm41_GBR_2.shp
gadm41_GBR_3.shp
gadm41_GBR_4.shp
这些文件可以在这里找到: https://geodata.ucdavis.edu/gadm/gadm4.1/shp/gadm41_GBR_shp.zip
这是我的全部代码:
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
# Load the UK shapefile (ensure this is the correct path to your UK counties shapefile)
uk_shapefile_path = "shp_files/gadm41_GBR_3.shp"
uk = gpd.read_file(uk_shapefile_path)
# Merge the shapefile with the data based on county name
# Merge the shapefile with the data based on county name
# You may need to adjust 'county_name' to match the column in the shapefile, like 'NAME' or 'COUNTY'
merged = uk.merge(df, left_on='NAME_2', right_on='county_name', how='left')
# Plot the heatmap of counties with the normalized count as the color scale
fig, ax = plt.subplots(1, 1, figsize=(10, 10))
merged.boundary.plot(ax=ax, linewidth=1, color='black')
merged.plot(column='normalized_count', ax=ax, cmap='YlOrBr', legend=False)
ax.set_xticks([])
ax.set_yticks([])
plt.title('XXXX by Counties')
plt.show()