为什么我不能用 python 制作英国各县的热图?

问题描述 投票:0回答:2

我正在尝试使用英国县地图创建热图。我已经尝试了几个星期但没有成功。

这是我拥有的数据示例:

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

这是我最后一个错误。还有其他错误,我想我已经解决了它们。

pandas matplotlib maps geopandas
2个回答
1
投票

看起来您在数据转换/清理方面遇到了问题。它看起来不像绘图或 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')

它的样子是这样的:

enter image description here


0
投票

我无法绘制各县的原因与我想合并的正确 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()
© www.soinside.com 2019 - 2024. All rights reserved.