First, we are going to use the previous administrative data for Vietnam available at GADM.
import geopandas as gpd
import pandas as pd
geojson_file = 'https://geodata.ucdavis.edu/gadm/gadm4.1/json/gadm41_VNM_1.json.zip'
# Read in the GeoJSON file
gdata = gpd.read_file(geojson_file)
# plot
gdata.plot(column="NAME_1")
When you open the dataframe, you will see 63 rows, corresponding to 63 provinces.
print(gdata[['NAME_1','geometry']])
## NAME_1 geometry
## 0 AnGiang MULTIPOLYGON (((105.5486 10.4295, 105.5495 10....
## 1 BàRịa-VũngTàu MULTIPOLYGON (((107.0901 10.324, 107.0889 10.3...
## 2 BắcGiang MULTIPOLYGON (((106.2838 21.1323, 106.2734 21....
## 3 BắcKạn MULTIPOLYGON (((105.8724 21.8558, 105.8629 21....
## 4 BạcLiêu MULTIPOLYGON (((105.4244 9.0213, 105.4164 9.01...
## .. ... ...
## 58 TràVinh MULTIPOLYGON (((106.4135 9.5292, 106.4088 9.53...
## 59 TuyênQuang MULTIPOLYGON (((105.5104 21.6047, 105.5141 21....
## 60 VĩnhLong MULTIPOLYGON (((106.0632 9.9475, 106.0627 9.94...
## 61 VĩnhPhúc MULTIPOLYGON (((105.5713 21.1615, 105.5336 21....
## 62 YênBái MULTIPOLYGON (((104.7946 21.3352, 104.7908 21....
##
## [63 rows x 2 columns]
Now, we are going to see the names of all provinces
print(gdata['NAME_1'].unique())
## ['AnGiang' 'BàRịa-VũngTàu' 'BắcGiang' 'BắcKạn' 'BạcLiêu' 'BắcNinh'
## 'BếnTre' 'BìnhĐịnh' 'BìnhDương' 'BìnhPhước' 'BìnhThuận' 'CàMau' 'CầnThơ'
## 'CaoBằng' 'ĐàNẵng' 'ĐắkLắk' 'ĐắkNông' 'ĐiệnBiên' 'ĐồngNai' 'ĐồngTháp'
## 'GiaLai' 'HàGiang' 'HàNam' 'HàNội' 'HàTĩnh' 'HảiDương' 'HảiPhòng'
## 'HậuGiang' 'HồChíMinh' 'HoàBình' 'HưngYên' 'KhánhHòa' 'KiênGiang'
## 'KonTum' 'LaiChâu' 'LâmĐồng' 'LạngSơn' 'LàoCai' 'LongAn' 'NamĐịnh'
## 'NghệAn' 'NinhBình' 'NinhThuận' 'PhúThọ' 'PhúYên' 'QuảngBình' 'QuảngNam'
## 'QuảngNgãi' 'QuảngNinh' 'QuảngTrị' 'SócTrăng' 'SơnLa' 'TâyNinh'
## 'TháiBình' 'TháiNguyên' 'ThanhHóa' 'ThừaThiênHuế' 'TiềnGiang' 'TràVinh'
## 'TuyênQuang' 'VĩnhLong' 'VĩnhPhúc' 'YênBái']
First, I need to define a list of all the merges. This has to be done manually. Note that the final name of the merged province must be put as the first element of a list.
# Define all the merges
merges = [
["TuyênQuang", "HàGiang"],
["LàoCai", "YênBái"],
["TháiNguyên", "BắcKạn"],
["PhúThọ", "VĩnhPhúc", "HoàBình"],
["BắcNinh", "BắcGiang"],
["HưngYên", "TháiBình"],
["HảiPhòng", "HảiDương"],
["NinhBình", "NamĐịnh", "HàNam"],
["QuảngBình", "QuảngTrị"],
["ĐàNẵng", "QuảngNam"],
["QuảngNgãi", "KonTum"],
["GiaLai", "BìnhĐịnh"],
["KhánhHòa", "NinhThuận"],
["LâmĐồng", "BìnhThuận", "ĐắkNông"],
["ĐắkLắk", "PhúYên"],
["HồChíMinh", "BìnhDương", "BàRịa-VũngTàu"],
["ĐồngNai", "BìnhPhước"],
["TâyNinh", "LongAn"],
["CầnThơ", "SócTrăng", "HậuGiang"],
["VĩnhLong", "BếnTre", "TràVinh"],
["ĐồngTháp", "TiềnGiang"],
["CàMau", "BạcLiêu"],
["AnGiang", "KiênGiang"]
]
The merge procedure is then done as follows.
We will loop through each list in the merged list. In each loop, here
is what we’re going to do: - subset the rows that include the provinces
to be merged - merge their geometry using union_all()
function - create a new province (row) with new NAME_1 and
geometry, with origins include the original
provices before the merge - delete the old rows from the old dataset and
insert the new row.
# Start with a copy of the original
gdata_new = gdata.copy()
# Loop through each merge group
for group in merges:
# Subset the rows to be merged
to_merge = gdata_new[gdata_new['NAME_1'].isin(group)]
# Merge the geometries
merged_geom = to_merge.union_all()
# Create new merged row with first name in group
merged_row = gpd.GeoDataFrame({
'NAME_1': [group[0]],
'geometry': [merged_geom],
'origins':[group]
},
crs=gdata_new.crs
)
# Drop old rows and append new one
gdata_new = gdata_new[~gdata_new['NAME_1'].isin(group)].copy()
gdata_new = pd.concat([gdata_new, merged_row], ignore_index=True)
# Replace NaN with NAME_1
gdata_new['origins'] = gdata_new['origins'].fillna(gdata_new['NAME_1'])
print(gdata_new[['NAME_1','origins']])
## NAME_1 origins
## 0 CaoBằng CaoBằng
## 1 ĐiệnBiên ĐiệnBiên
## 2 HàNội HàNội
## 3 HàTĩnh HàTĩnh
## 4 LaiChâu LaiChâu
## 5 LạngSơn LạngSơn
## 6 NghệAn NghệAn
## 7 QuảngNinh QuảngNinh
## 8 SơnLa SơnLa
## 9 ThanhHóa ThanhHóa
## 10 ThừaThiênHuế ThừaThiênHuế
## 11 TuyênQuang [TuyênQuang, HàGiang]
## 12 LàoCai [LàoCai, YênBái]
## 13 TháiNguyên [TháiNguyên, BắcKạn]
## 14 PhúThọ [PhúThọ, VĩnhPhúc, HoàBình]
## 15 BắcNinh [BắcNinh, BắcGiang]
## 16 HưngYên [HưngYên, TháiBình]
## 17 HảiPhòng [HảiPhòng, HảiDương]
## 18 NinhBình [NinhBình, NamĐịnh, HàNam]
## 19 QuảngBình [QuảngBình, QuảngTrị]
## 20 ĐàNẵng [ĐàNẵng, QuảngNam]
## 21 QuảngNgãi [QuảngNgãi, KonTum]
## 22 GiaLai [GiaLai, BìnhĐịnh]
## 23 KhánhHòa [KhánhHòa, NinhThuận]
## 24 LâmĐồng [LâmĐồng, BìnhThuận, ĐắkNông]
## 25 ĐắkLắk [ĐắkLắk, PhúYên]
## 26 HồChíMinh [HồChíMinh, BìnhDương, BàRịa-VũngTàu]
## 27 ĐồngNai [ĐồngNai, BìnhPhước]
## 28 TâyNinh [TâyNinh, LongAn]
## 29 CầnThơ [CầnThơ, SócTrăng, HậuGiang]
## 30 VĩnhLong [VĩnhLong, BếnTre, TràVinh]
## 31 ĐồngTháp [ĐồngTháp, TiềnGiang]
## 32 CàMau [CàMau, BạcLiêu]
## 33 AnGiang [AnGiang, KiênGiang]
Printing out gdata_new, you will see that it has only 34
rows, which corresponds to the new set of provinces. Those with
NaN in column origins indicate provinces
without any changes, so we just set their value to be the same as
‘NAME_1’.
We can also use plotly to show an interactive plot.
import plotly.express as px
import pyproj
fig = px.choropleth(
gdata_new,
geojson=gdata_new.geometry,
locations=gdata_new.index,
color="NAME_1",
hover_data=["origins"],
labels={"NAME_1": "Province"}
)
fig.update_geos(fitbounds="locations", visible=False)