5.3 EU Population Analysis¶
Go to Eurostat Database and choose Population and social conditions-> Demography, population stock and balance -> Population on 1 January by broad age group, sex and NUTS 3 region.
In data viewer download full dataset in CSV format.
Load data¶
filename = 'demo_r_pjanaggr3_linear.csv.gz'
import pandas as pd
df = pd.read_csv(filename, compression='gzip')
Show loaded data.
df
DATAFLOW | LAST UPDATE | freq | unit | sex | age | geo | TIME_PERIOD | OBS_VALUE | OBS_FLAG | |
---|---|---|---|---|---|---|---|---|---|---|
0 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | AL | 2000 | 1526762.0 | NaN |
1 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | AL | 2001 | 1535822.0 | NaN |
2 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | AL | 2002 | 1532563.0 | NaN |
3 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | AL | 2003 | 1526180.0 | NaN |
4 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | AL | 2004 | 1520481.0 | NaN |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
623400 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | UKN16 | 2015 | 23318.0 | NaN |
623401 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | UKN16 | 2016 | 23394.0 | NaN |
623402 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | UKN16 | 2017 | 23555.0 | NaN |
623403 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | UKN16 | 2018 | 23646.0 | NaN |
623404 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | UKN16 | 2019 | 23743.0 | NaN |
623405 rows × 10 columns
Unique values¶
df["sex"].unique()
array(['F', 'M', 'T'], dtype=object)
df["TIME_PERIOD"].unique()
array([2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2022])
Let's sort items.
df["TIME_PERIOD"].sort_values().unique()
array([1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022])
Filter data¶
Filter by single column.
df[df["geo"] == "CZ"]
DATAFLOW | LAST UPDATE | freq | unit | sex | age | geo | TIME_PERIOD | OBS_VALUE | OBS_FLAG | |
---|---|---|---|---|---|---|---|---|---|---|
4890 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | CZ | 1990 | 5326444.0 | NaN |
4891 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | CZ | 1991 | 5303641.0 | NaN |
4892 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | CZ | 1992 | 5306546.0 | NaN |
4893 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | CZ | 1993 | 5312284.0 | NaN |
4894 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | F | TOTAL | CZ | 1994 | 5314716.0 | NaN |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
587869 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | CZ | 2017 | 1647275.0 | NaN |
587870 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | CZ | 2018 | 1670677.0 | NaN |
587871 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | CZ | 2019 | 1693060.0 | NaN |
587872 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | CZ | 2020 | 1710202.0 | NaN |
587873 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | Y_LT15 | CZ | 2021 | 1719741.0 | NaN |
477 rows × 10 columns
Filter by multiple columns.
df[(df["geo"] == "CZ") & (df["TIME_PERIOD"] == 2021) & (df["sex"] == 'T') & (df["age"] == 'TOTAL')]
DATAFLOW | LAST UPDATE | freq | unit | sex | age | geo | TIME_PERIOD | OBS_VALUE | OBS_FLAG | |
---|---|---|---|---|---|---|---|---|---|---|
420523 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | CZ | 2021 | 10701777.0 | NaN |
Let's define a new function which returns population records for selected NUTS code and year.
def population_by_country(code, year):
return int(df[(df["geo"] == code) & (df["TIME_PERIOD"] == year) & (df["sex"] == 'T') & (df["age"] == 'TOTAL')]["OBS_VALUE"].values[0])
population_by_country('CZ', 2021)
10701777
population_by_country('DE', 2021)
83155031
Second fuction prototype returns population by sex (male, female, total).
def population_by_country_sex(code, year):
return df[(df["geo"] == code) & (df["TIME_PERIOD"] == year) & (df["age"] == 'TOTAL')][["sex", "OBS_VALUE"]].to_dict('list')
population_by_country_sex('CZ', 2021)
{'sex': ['F', 'M', 'T'], 'OBS_VALUE': [5426674.0, 5275103.0, 10701777.0]}
Third function prototype also returns percentage of female in population. Return object is modified to dictionary.
def population_by_country_sex_p(code, year):
res = df[(df["geo"] == code) & (df["TIME_PERIOD"] == year) & (df["age"] == 'TOTAL')][["sex", "OBS_VALUE"]].to_dict('list')
f_idx = res["sex"].index("F")
f = res["OBS_VALUE"][f_idx]
t_idx = res["sex"].index("T")
t = res["OBS_VALUE"][t_idx]
res_dict = {}
i = 0
for k in res["sex"]:
res_dict[k] = int(res["OBS_VALUE"][i])
i += 1
res_dict["F_p"] = round(f/t, 2)
return res_dict
population_by_country_sex_p('CZ', 2021)
{'F': 5426674, 'M': 5275103, 'T': 10701777, 'F_p': 0.51}
population_by_country_sex_p('ES', 2021)
{'F': 24171413, 'M': 23227282, 'T': 47398695, 'F_p': 0.51}
Filter data by NUTS level¶
df[(df["TIME_PERIOD"] == 2021) & (df["sex"] == 'T') & (df["age"] == 'TOTAL')]
DATAFLOW | LAST UPDATE | freq | unit | sex | age | geo | TIME_PERIOD | OBS_VALUE | OBS_FLAG | |
---|---|---|---|---|---|---|---|---|---|---|
415619 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | AL | 2021 | 2829741.0 | NaN |
415644 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | AL0 | 2021 | 2829741.0 | NaN |
415654 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | AL01 | 2021 | 797955.0 | NaN |
415664 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | AL011 | 2021 | 113683.0 | NaN |
415674 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | AL012 | 2021 | 292029.0 | NaN |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
457918 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | TRC3 | 2021 | 2343826.0 | NaN |
457939 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | TRC31 | 2021 | 854716.0 | NaN |
457960 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | TRC32 | 2021 | 620278.0 | NaN |
457981 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | TRC33 | 2021 | 537762.0 | NaN |
458002 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | TRC34 | 2021 | 331070.0 | NaN |
1776 rows × 10 columns
Filter NUTS level 0 (two character code).
df[(df["TIME_PERIOD"] == 2021) & (df["sex"] == 'T') & (df["age"] == 'TOTAL') & (df["geo"].apply(lambda x: len(x) == 2))].head(10)
DATAFLOW | LAST UPDATE | freq | unit | sex | age | geo | TIME_PERIOD | OBS_VALUE | OBS_FLAG | |
---|---|---|---|---|---|---|---|---|---|---|
415619 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | AL | 2021 | 2829741.0 | NaN |
415847 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | AT | 2021 | 8932664.0 | NaN |
416879 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | BE | 2021 | 11554767.0 | NaN |
418235 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | BG | 2021 | 6916548.0 | NaN |
419275 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | CH | 2021 | 8670300.0 | NaN |
420395 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | CY | 2021 | 896007.0 | NaN |
420523 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | CZ | 2021 | 10701777.0 | NaN |
421096 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | DE | 2021 | 83155031.0 | NaN |
430839 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | DK | 2021 | 5840045.0 | NaN |
431133 | ESTAT:DEMO_R_PJANAGGR3(1.0) | 20/03/23 23:00:00 | A | NR | T | TOTAL | EE | 2021 | 1330068.0 | NaN |
Define a new function which filter data based on specified year, NUTS level and sex. Optionally filter may be extended by NUTS code pattern.
def population_by_nuts(year, level=0, sex='T', nuts=None):
data = df[(df["TIME_PERIOD"] == year) & (df["sex"] == sex) & (df["age"] == 'TOTAL') & (df["geo"].apply(lambda x: len(x) == level+2))]
if nuts:
data = data[data["geo"].str.match(nuts)]
return data[["geo", "OBS_VALUE"]]
population_by_nuts(2021)
geo | OBS_VALUE | |
---|---|---|
415619 | AL | 2829741.0 |
415847 | AT | 8932664.0 |
416879 | BE | 11554767.0 |
418235 | BG | 6916548.0 |
419275 | CH | 8670300.0 |
420395 | CY | 896007.0 |
420523 | CZ | 10701777.0 |
421096 | DE | 83155031.0 |
430839 | DK | 5840045.0 |
431133 | EE | 1330068.0 |
431351 | EL | 10678632.0 |
433528 | ES | 47398695.0 |
436252 | FI | 5533793.0 |
437116 | FR | 67656682.0 |
441589 | HR | 4036355.0 |
442128 | HU | 9730772.0 |
442880 | IE | 5006324.0 |
443049 | IS | 368792.0 |
443168 | IT | 59236213.0 |
446447 | LI | 39055.0 |
446575 | LT | 2795680.0 |
446895 | LU | 634730.0 |
447027 | LV | 1893223.0 |
447228 | ME | 620739.0 |
447326 | MK | 2068808.0 |
447659 | MT | 516100.0 |
447797 | NL | 17475415.0 |
448870 | NO | 5391369.0 |
449390 | PL | 37840001.0 |
451363 | PT | 10298252.0 |
452445 | RO | 19201662.0 |
453924 | RS | 6871547.0 |
454143 | SE | 10379295.0 |
454879 | SI | 2108977.0 |
455199 | SK | 5459781.0 |
455503 | TR | 83614362.0 |
population_by_nuts(2019, level=2, sex="F", nuts="CZ")
geo | OBS_VALUE | |
---|---|---|
4967 | CZ01 | 670623.0 |
5015 | CZ02 | 692636.0 |
5063 | CZ03 | 619311.0 |
5133 | CZ04 | 562616.0 |
5203 | CZ05 | 766363.0 |
5296 | CZ06 | 861364.0 |
5366 | CZ07 | 619910.0 |
5436 | CZ08 | 612783.0 |
Graphs¶
data = population_by_nuts(2021)
data.plot(kind="barh", x="geo", y="OBS_VALUE", xlabel="NUTS0", ylabel="Population",
title=f"Population (2021, total)", figsize=(20, 15))
<AxesSubplot:title={'center':'Population (2021, total)'}, xlabel='NUTS0', ylabel='Population'>
Let's define a new function which prints graph for specified year, NUTS level and optionally NUTS code pattern.
def print_graph(year, level=0, sex="T", nuts=None):
data = population_by_nuts(year, level, sex, nuts)
data.plot(kind="barh", x="geo", y="OBS_VALUE", xlabel=f"NUTS{level}", ylabel="Population",
title=f"Population ({year} {sex})", figsize=(20, 15))
print_graph(2021, level=1, nuts="DE")
# TODO: F, M
print_graph(1990, level=1, nuts="ES", sex="F")
GeoPandas¶
!unzip 01.zip
import geopandas as gpd
nuts = gpd.read_file("01/NUTS_RG_20M_2021_3035.shp")
nuts
NUTS_ID | LEVL_CODE | CNTR_CODE | NAME_LATN | NUTS_NAME | MOUNT_TYPE | URBN_TYPE | COAST_TYPE | FID | geometry | |
---|---|---|---|---|---|---|---|---|---|---|
0 | FR | 0 | FR | France | France | 0.0 | 0 | 0 | FR | MULTIPOLYGON (((9954236.116 -3059379.316, 9961... |
1 | HR | 0 | HR | Hrvatska | Hrvatska | 0.0 | 0 | 0 | HR | MULTIPOLYGON (((4827385.889 2618351.326, 48483... |
2 | HU | 0 | HU | Magyarország | Magyarország | 0.0 | 0 | 0 | HU | POLYGON ((5214660.069 2880853.832, 5216710.220... |
3 | AL | 0 | AL | Shqipëria | Shqipëria | 0.0 | 0 | 0 | AL | POLYGON ((5129579.170 2204098.752, 5148385.473... |
4 | AT | 0 | AT | Österreich | Österreich | 0.0 | 0 | 0 | AT | POLYGON ((4742889.368 2876362.725, 4783217.798... |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2005 | TRC21 | 3 | TR | Şanlıurfa | Şanlıurfa | 4.0 | 2 | 3 | TRC21 | POLYGON ((6904684.585 2120354.802, 6938677.828... |
2006 | TRC22 | 3 | TR | Diyarbakır | Diyarbakır | 4.0 | 2 | 3 | TRC22 | POLYGON ((6989716.599 2273670.524, 6982786.486... |
2007 | NO0B2 | 3 | NO | Svalbard | Svalbard | 3.0 | 3 | 1 | NO0B2 | MULTIPOLYGON (((4754167.335 6382461.409, 47465... |
2008 | NO0B | 2 | NO | Jan Mayen and Svalbard | Jan Mayen and Svalbard | NaN | 0 | 0 | NO0B | MULTIPOLYGON (((4754167.335 6382461.409, 47465... |
2009 | NO0B1 | 3 | NO | Jan Mayen | Jan Mayen | 3.0 | 3 | 1 | NO0B1 | POLYGON ((3642785.362 5404637.884, 3624291.510... |
2010 rows × 10 columns
Filter features by NUTS level.
nuts0 = nuts[nuts["LEVL_CODE"] == 0]
nuts0
NUTS_ID | LEVL_CODE | CNTR_CODE | NAME_LATN | NUTS_NAME | MOUNT_TYPE | URBN_TYPE | COAST_TYPE | FID | geometry | |
---|---|---|---|---|---|---|---|---|---|---|
0 | FR | 0 | FR | France | France | 0.0 | 0 | 0 | FR | MULTIPOLYGON (((9954236.116 -3059379.316, 9961... |
1 | HR | 0 | HR | Hrvatska | Hrvatska | 0.0 | 0 | 0 | HR | MULTIPOLYGON (((4827385.889 2618351.326, 48483... |
2 | HU | 0 | HU | Magyarország | Magyarország | 0.0 | 0 | 0 | HU | POLYGON ((5214660.069 2880853.832, 5216710.220... |
3 | AL | 0 | AL | Shqipëria | Shqipëria | 0.0 | 0 | 0 | AL | POLYGON ((5129579.170 2204098.752, 5148385.473... |
4 | AT | 0 | AT | Österreich | Österreich | 0.0 | 0 | 0 | AT | POLYGON ((4742889.368 2876362.725, 4783217.798... |
5 | BE | 0 | BE | Belgique/België | Belgique/België | 0.0 | 0 | 0 | BE | POLYGON ((3957506.818 3167694.476, 3964175.126... |
6 | BG | 0 | BG | Bulgaria | България | 0.0 | 0 | 0 | BG | POLYGON ((5363358.686 2390534.464, 5395245.631... |
7 | CH | 0 | CH | Schweiz/Suisse/Svizzera | Schweiz/Suisse/Svizzera | 0.0 | 0 | 0 | CH | POLYGON ((4221123.476 2731035.919, 4230514.931... |
8 | CY | 0 | CY | Kýpros | Κύπρος | 0.0 | 0 | 0 | CY | POLYGON ((6342668.882 1629618.498, 6342926.802... |
9 | CZ | 0 | CZ | Česko | Česko | 0.0 | 0 | 0 | CZ | POLYGON ((4645979.160 3093185.023, 4656689.778... |
10 | DE | 0 | DE | Deutschland | Deutschland | 0.0 | 0 | 0 | DE | MULTIPOLYGON (((4264045.786 3530123.440, 42755... |
11 | DK | 0 | DK | Danmark | Danmark | 0.0 | 0 | 0 | DK | MULTIPOLYGON (((4649970.056 3564245.706, 46461... |
12 | EE | 0 | EE | Eesti | Eesti | 0.0 | 0 | 0 | EE | MULTIPOLYGON (((5209290.379 4151086.253, 52115... |
21 | EL | 0 | EL | Elláda | Ελλάδα | 0.0 | 0 | 0 | EL | MULTIPOLYGON (((5933660.592 1621535.498, 59219... |
22 | IE | 0 | IE | Éire/Ireland | Éire/Ireland | 0.0 | 0 | 0 | IE | MULTIPOLYGON (((3230329.820 3682748.467, 31996... |
23 | ES | 0 | ES | España | España | 0.0 | 0 | 0 | ES | MULTIPOLYGON (((3828319.814 1893178.953, 38317... |
24 | FI | 0 | FI | Suomi/Finland | Suomi/Finland | 0.0 | 0 | 0 | FI | MULTIPOLYGON (((5073773.420 5207018.495, 50659... |
25 | IS | 0 | IS | Ísland | Ísland | 0.0 | 0 | 0 | IS | POLYGON ((2801938.567 4882218.079, 2796614.316... |
27 | PT | 0 | PT | Portugal | Portugal | 0.0 | 0 | 0 | PT | MULTIPOLYGON (((2822605.491 2261163.044, 28317... |
28 | RO | 0 | RO | România | România | 0.0 | 0 | 0 | RO | POLYGON ((5616141.550 2872864.277, 5661531.895... |
29 | RS | 0 | RS | Serbia | Srbija/Сpбија | 0.0 | 0 | 0 | RS | POLYGON ((5112369.786 2611777.777, 5147917.997... |
30 | SE | 0 | SE | Sverige | Sverige | 0.0 | 0 | 0 | SE | MULTIPOLYGON (((4968500.376 4802688.699, 49724... |
31 | SI | 0 | SI | Slovenija | Slovenija | 0.0 | 0 | 0 | SI | POLYGON ((4807826.153 2644113.739, 4827385.889... |
32 | SK | 0 | SK | Slovensko | Slovensko | 0.0 | 0 | 0 | SK | POLYGON ((5038951.099 2947340.447, 5053038.090... |
33 | TR | 0 | TR | Türkiye | Türkiye | 0.0 | 0 | 0 | TR | MULTIPOLYGON (((6409166.817 2417609.250, 64213... |
42 | UK | 0 | UK | United Kingdom | United Kingdom | 0.0 | 0 | 0 | UK | MULTIPOLYGON (((3643416.574 3198789.397, 36397... |
44 | NO | 0 | NO | Norge | Norge | 0.0 | 0 | 0 | NO | MULTIPOLYGON (((5073773.420 5207018.495, 50670... |
61 | IT | 0 | IT | Italia | Italia | 0.0 | 0 | 0 | IT | MULTIPOLYGON (((4510728.830 2621660.509, 45270... |
62 | LI | 0 | LI | Liechtenstein | Liechtenstein | 0.0 | 0 | 0 | LI | POLYGON ((4281155.780 2659947.764, 4285464.426... |
63 | LT | 0 | LT | Lietuva | Lietuva | 0.0 | 0 | 0 | LT | POLYGON ((5298223.159 3769132.577, 5303983.134... |
64 | LU | 0 | LU | Luxembourg | Luxembourg | 0.0 | 0 | 0 | LU | POLYGON ((4044953.867 3009232.573, 4046925.344... |
65 | LV | 0 | LV | Latvija | Latvija | 0.0 | 0 | 0 | LV | POLYGON ((5350178.139 3949790.862, 5360225.824... |
66 | ME | 0 | ME | Crna Gora | Црна Гора | 0.0 | 0 | 0 | ME | POLYGON ((5066457.268 2314658.245, 5106789.821... |
67 | MK | 0 | MK | Severna Makedonija | Северна Македонија | 0.0 | 0 | 0 | MK | POLYGON ((5338319.640 2217739.395, 5347083.127... |
68 | MT | 0 | MT | Malta | Malta | 0.0 | 0 | 0 | MT | MULTIPOLYGON (((4737037.613 1433526.447, 47322... |
69 | NL | 0 | NL | Nederland | Nederland | 0.0 | 0 | 0 | NL | MULTIPOLYGON (((4113226.333 3371154.950, 41159... |
84 | PL | 0 | PL | Polska | Polska | 0.0 | 0 | 0 | PL | POLYGON ((4901276.725 3508415.463, 4926344.597... |
Show features in interactive map.
nuts0.explore()
Merge population values¶
popu = population_by_nuts(2021)
nuts0_popu = pd.merge(nuts0, popu, how='left', left_on='NUTS_ID', right_on='geo')
nuts0_popu.head(10)
NUTS_ID | LEVL_CODE | CNTR_CODE | NAME_LATN | NUTS_NAME | MOUNT_TYPE | URBN_TYPE | COAST_TYPE | FID | geometry | geo | OBS_VALUE | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | FR | 0 | FR | France | France | 0.0 | 0 | 0 | FR | MULTIPOLYGON (((9954236.116 -3059379.316, 9961... | FR | 67656682.0 |
1 | HR | 0 | HR | Hrvatska | Hrvatska | 0.0 | 0 | 0 | HR | MULTIPOLYGON (((4827385.889 2618351.326, 48483... | HR | 4036355.0 |
2 | HU | 0 | HU | Magyarország | Magyarország | 0.0 | 0 | 0 | HU | POLYGON ((5214660.069 2880853.832, 5216710.220... | HU | 9730772.0 |
3 | AL | 0 | AL | Shqipëria | Shqipëria | 0.0 | 0 | 0 | AL | POLYGON ((5129579.170 2204098.752, 5148385.473... | AL | 2829741.0 |
4 | AT | 0 | AT | Österreich | Österreich | 0.0 | 0 | 0 | AT | POLYGON ((4742889.368 2876362.725, 4783217.798... | AT | 8932664.0 |
5 | BE | 0 | BE | Belgique/België | Belgique/België | 0.0 | 0 | 0 | BE | POLYGON ((3957506.818 3167694.476, 3964175.126... | BE | 11554767.0 |
6 | BG | 0 | BG | Bulgaria | България | 0.0 | 0 | 0 | BG | POLYGON ((5363358.686 2390534.464, 5395245.631... | BG | 6916548.0 |
7 | CH | 0 | CH | Schweiz/Suisse/Svizzera | Schweiz/Suisse/Svizzera | 0.0 | 0 | 0 | CH | POLYGON ((4221123.476 2731035.919, 4230514.931... | CH | 8670300.0 |
8 | CY | 0 | CY | Kýpros | Κύπρος | 0.0 | 0 | 0 | CY | POLYGON ((6342668.882 1629618.498, 6342926.802... | CY | 896007.0 |
9 | CZ | 0 | CZ | Česko | Česko | 0.0 | 0 | 0 | CZ | POLYGON ((4645979.160 3093185.023, 4656689.778... | CZ | 10701777.0 |
Show features symbolized by population value.
nuts0_popu.explore(column='OBS_VALUE', legend=False, cmap='OrRd')
Let's put it together.
def nuts_population(year, level):
nuts_level = nuts[nuts["LEVL_CODE"] == level]
popu = population_by_nuts(year, level)
return pd.merge(nuts_level, popu, how='left', left_on='NUTS_ID', right_on='geo')
nuts_popu = nuts_population(2005, 1)
nuts_popu.explore(column='OBS_VALUE', legend=False, cmap='OrRd')
nuts_population(1990, 2).explore(column='OBS_VALUE', legend=False, cmap='OrRd')
Population density¶
nuts0_popu.area.head(10)
0 6.387388e+11 1 5.658665e+10 2 9.296786e+10 3 2.866265e+10 4 8.385113e+10 5 3.075490e+10 6 1.113900e+11 7 4.105576e+10 8 9.240976e+09 9 7.889687e+10 dtype: float64
Compute population density (persons/km2).
(nuts0_popu["OBS_VALUE"] / (nuts0_popu.area / 1e6)).head(10)
0 105.922303 1 71.330521 2 104.668134 3 98.725738 4 106.530037 5 375.704856 6 62.093084 7 211.183535 8 96.960210 9 135.642602 dtype: float64
nuts0_popu["density"] = nuts0_popu["OBS_VALUE"] / (nuts0_popu.area / 1e6)
nuts0_popu
NUTS_ID | LEVL_CODE | CNTR_CODE | NAME_LATN | NUTS_NAME | MOUNT_TYPE | URBN_TYPE | COAST_TYPE | FID | geometry | geo | OBS_VALUE | density | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | FR | 0 | FR | France | France | 0.0 | 0 | 0 | FR | MULTIPOLYGON (((9954236.116 -3059379.316, 9961... | FR | 67656682.0 | 105.922303 |
1 | HR | 0 | HR | Hrvatska | Hrvatska | 0.0 | 0 | 0 | HR | MULTIPOLYGON (((4827385.889 2618351.326, 48483... | HR | 4036355.0 | 71.330521 |
2 | HU | 0 | HU | Magyarország | Magyarország | 0.0 | 0 | 0 | HU | POLYGON ((5214660.069 2880853.832, 5216710.220... | HU | 9730772.0 | 104.668134 |
3 | AL | 0 | AL | Shqipëria | Shqipëria | 0.0 | 0 | 0 | AL | POLYGON ((5129579.170 2204098.752, 5148385.473... | AL | 2829741.0 | 98.725738 |
4 | AT | 0 | AT | Österreich | Österreich | 0.0 | 0 | 0 | AT | POLYGON ((4742889.368 2876362.725, 4783217.798... | AT | 8932664.0 | 106.530037 |
5 | BE | 0 | BE | Belgique/België | Belgique/België | 0.0 | 0 | 0 | BE | POLYGON ((3957506.818 3167694.476, 3964175.126... | BE | 11554767.0 | 375.704856 |
6 | BG | 0 | BG | Bulgaria | България | 0.0 | 0 | 0 | BG | POLYGON ((5363358.686 2390534.464, 5395245.631... | BG | 6916548.0 | 62.093084 |
7 | CH | 0 | CH | Schweiz/Suisse/Svizzera | Schweiz/Suisse/Svizzera | 0.0 | 0 | 0 | CH | POLYGON ((4221123.476 2731035.919, 4230514.931... | CH | 8670300.0 | 211.183535 |
8 | CY | 0 | CY | Kýpros | Κύπρος | 0.0 | 0 | 0 | CY | POLYGON ((6342668.882 1629618.498, 6342926.802... | CY | 896007.0 | 96.960210 |
9 | CZ | 0 | CZ | Česko | Česko | 0.0 | 0 | 0 | CZ | POLYGON ((4645979.160 3093185.023, 4656689.778... | CZ | 10701777.0 | 135.642602 |
10 | DE | 0 | DE | Deutschland | Deutschland | 0.0 | 0 | 0 | DE | MULTIPOLYGON (((4264045.786 3530123.440, 42755... | DE | 83155031.0 | 232.690648 |
11 | DK | 0 | DK | Danmark | Danmark | 0.0 | 0 | 0 | DK | MULTIPOLYGON (((4649970.056 3564245.706, 46461... | DK | 5840045.0 | 134.224934 |
12 | EE | 0 | EE | Eesti | Eesti | 0.0 | 0 | 0 | EE | MULTIPOLYGON (((5209290.379 4151086.253, 52115... | EE | 1330068.0 | 29.401785 |
13 | EL | 0 | EL | Elláda | Ελλάδα | 0.0 | 0 | 0 | EL | MULTIPOLYGON (((5933660.592 1621535.498, 59219... | EL | 10678632.0 | 81.248372 |
14 | IE | 0 | IE | Éire/Ireland | Éire/Ireland | 0.0 | 0 | 0 | IE | MULTIPOLYGON (((3230329.820 3682748.467, 31996... | IE | 5006324.0 | 71.912373 |
15 | ES | 0 | ES | España | España | 0.0 | 0 | 0 | ES | MULTIPOLYGON (((3828319.814 1893178.953, 38317... | ES | 47398695.0 | 93.675050 |
16 | FI | 0 | FI | Suomi/Finland | Suomi/Finland | 0.0 | 0 | 0 | FI | MULTIPOLYGON (((5073773.420 5207018.495, 50659... | FI | 5533793.0 | 16.344541 |
17 | IS | 0 | IS | Ísland | Ísland | 0.0 | 0 | 0 | IS | POLYGON ((2801938.567 4882218.079, 2796614.316... | IS | 368792.0 | 3.604129 |
18 | PT | 0 | PT | Portugal | Portugal | 0.0 | 0 | 0 | PT | MULTIPOLYGON (((2822605.491 2261163.044, 28317... | PT | 10298252.0 | 111.299685 |
19 | RO | 0 | RO | România | România | 0.0 | 0 | 0 | RO | POLYGON ((5616141.550 2872864.277, 5661531.895... | RO | 19201662.0 | 80.671616 |
20 | RS | 0 | RS | Serbia | Srbija/Сpбија | 0.0 | 0 | 0 | RS | POLYGON ((5112369.786 2611777.777, 5147917.997... | RS | 6871547.0 | 88.968320 |
21 | SE | 0 | SE | Sverige | Sverige | 0.0 | 0 | 0 | SE | MULTIPOLYGON (((4968500.376 4802688.699, 49724... | SE | 10379295.0 | 22.930061 |
22 | SI | 0 | SI | Slovenija | Slovenija | 0.0 | 0 | 0 | SI | POLYGON ((4807826.153 2644113.739, 4827385.889... | SI | 2108977.0 | 104.674268 |
23 | SK | 0 | SK | Slovensko | Slovensko | 0.0 | 0 | 0 | SK | POLYGON ((5038951.099 2947340.447, 5053038.090... | SK | 5459781.0 | 111.608907 |
24 | TR | 0 | TR | Türkiye | Türkiye | 0.0 | 0 | 0 | TR | MULTIPOLYGON (((6409166.817 2417609.250, 64213... | TR | 83614362.0 | 107.217957 |
25 | UK | 0 | UK | United Kingdom | United Kingdom | 0.0 | 0 | 0 | UK | MULTIPOLYGON (((3643416.574 3198789.397, 36397... | NaN | NaN | NaN |
26 | NO | 0 | NO | Norge | Norge | 0.0 | 0 | 0 | NO | MULTIPOLYGON (((5073773.420 5207018.495, 50670... | NO | 5391369.0 | 13.545236 |
27 | IT | 0 | IT | Italia | Italia | 0.0 | 0 | 0 | IT | MULTIPOLYGON (((4510728.830 2621660.509, 45270... | IT | 59236213.0 | 196.048849 |
28 | LI | 0 | LI | Liechtenstein | Liechtenstein | 0.0 | 0 | 0 | LI | POLYGON ((4281155.780 2659947.764, 4285464.426... | LI | 39055.0 | 243.932094 |
29 | LT | 0 | LT | Lietuva | Lietuva | 0.0 | 0 | 0 | LT | POLYGON ((5298223.159 3769132.577, 5303983.134... | LT | 2795680.0 | 43.287231 |
30 | LU | 0 | LU | Luxembourg | Luxembourg | 0.0 | 0 | 0 | LU | POLYGON ((4044953.867 3009232.573, 4046925.344... | LU | 634730.0 | 241.574983 |
31 | LV | 0 | LV | Latvija | Latvija | 0.0 | 0 | 0 | LV | POLYGON ((5350178.139 3949790.862, 5360225.824... | LV | 1893223.0 | 29.285752 |
32 | ME | 0 | ME | Crna Gora | Црна Гора | 0.0 | 0 | 0 | ME | POLYGON ((5066457.268 2314658.245, 5106789.821... | ME | 620739.0 | 44.437366 |
33 | MK | 0 | MK | Severna Makedonija | Северна Македонија | 0.0 | 0 | 0 | MK | POLYGON ((5338319.640 2217739.395, 5347083.127... | MK | 2068808.0 | 81.473215 |
34 | MT | 0 | MT | Malta | Malta | 0.0 | 0 | 0 | MT | MULTIPOLYGON (((4737037.613 1433526.447, 47322... | MT | 516100.0 | 1873.060682 |
35 | NL | 0 | NL | Nederland | Nederland | 0.0 | 0 | 0 | NL | MULTIPOLYGON (((4113226.333 3371154.950, 41159... | NL | 17475415.0 | 469.613677 |
36 | PL | 0 | PL | Polska | Polska | 0.0 | 0 | 0 | PL | POLYGON ((4901276.725 3508415.463, 4926344.597... | PL | 37840001.0 | 121.093837 |
nuts0_popu.explore(column='density', legend=True, cmap='OrRd')
mean = nuts0_popu["density"].mean()
nuts0_popu.explore(column='density', legend=True, cmap='OrRd', vmax=mean)