Dati del Report di Roma - Abitare¶
In [1]:
import pandasdmx as sdmx
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio
pio.renderers.default = "plotly_mimetype+notebook"
Fonte OECD - OCSE¶
In [2]:
source_oecd = {
"id": "OECD_ADV",
"api_id": "OECD.ELS.SAE",
"name": "OECD",
"url": "https://sdmx.oecd.org/public/rest",
"supports": {
"provisionagreement": False,
"structure-specific data": False
}
}
sdmx.add_source(source_oecd, override=True)
oecd = sdmx.Request('OECD_ADV')
In [3]:
# flow_msg = oecd.dataflow()
# dataflows = pd.DataFrame(sdmx.to_pandas(flow_msg.dataflow)).reset_index(names='COD').rename(columns={0:'DESCR_IT'})
In [4]:
data_msg = oecd.data('DSD_EARNINGS@AV_AN_WAGE')
data_df = pd.DataFrame(sdmx.to_pandas(data_msg)).reset_index()
data_df = data_df[(data_df['REF_AREA'].isin(['ITA','OECD']))&(data_df['PRICE_BASE']=='Q')&(data_df['UNIT_MEASURE']=='USD_PPP')].copy()
data_df = data_df[['REF_AREA','TIME_PERIOD','value']].copy()
In [5]:
base_df = data_df[data_df['TIME_PERIOD']=='1996'].copy()
m = data_df.merge(base_df, on='REF_AREA', how='left')
m['v'] = m['value_x'] / m['value_y'] * 100
m['TIME_PERIOD'] = m['TIME_PERIOD_x'].astype(int)
In [6]:
layout = go.Layout(title='Salario medio - base 1996')
fig = go.Figure(layout=layout)
for ref in list(m['REF_AREA'].unique()):
temp = m[m['REF_AREA']==ref].sort_values(by='TIME_PERIOD').copy()
fig.add_trace(go.Scatter(x=temp['TIME_PERIOD'], y=temp['v'], name=ref,mode='lines+markers',marker=dict(size=5)))
fig.show()
In [7]:
data_msg = oecd.data('DSD_AN_HOUSE_PRICES@DF_HOUSE_PRICES')
data_df = pd.DataFrame(sdmx.to_pandas(data_msg)).reset_index()
In [8]:
df = data_df[(data_df['REF_AREA'].isin(['ITA','EA']))&(data_df['FREQ']=='A')&(data_df['MEASURE']=='RPI')&(data_df['TIME_PERIOD']>'1995')].copy()
df = df[['REF_AREA','TIME_PERIOD','value']].copy()
base_df = df[df['TIME_PERIOD']=='1996'].copy()
m = df.merge(base_df, on='REF_AREA', how='left')
m['v'] = m['value_x'] / m['value_y'] * 100
m['TIME_PERIOD'] = m['TIME_PERIOD_x'].astype(int)
layout = go.Layout(title='Canoni di affitto - base 1996')
fig = go.Figure(layout=layout)
for ref in list(m['REF_AREA'].unique()):
temp = m[m['REF_AREA']==ref].sort_values(by='TIME_PERIOD').copy()
fig.add_trace(go.Scatter(x=temp['TIME_PERIOD'], y=temp['v'], name=ref,mode='lines+markers',marker=dict(size=5)))
fig.show()
In [9]:
df = data_df[(data_df['REF_AREA'].isin(['ITA','EA']))&(data_df['FREQ']=='A')&(data_df['MEASURE']=='RHP')&(data_df['TIME_PERIOD']>'1995')].copy()
df = df[['REF_AREA','TIME_PERIOD','value']].copy()
base_df = df[df['TIME_PERIOD']=='1996'].copy()
m = df.merge(base_df, on='REF_AREA', how='left')
m['v'] = m['value_x'] / m['value_y'] * 100
m['TIME_PERIOD'] = m['TIME_PERIOD_x'].astype(int)
layout = go.Layout(title='Prezzo di compravendita - base 1996')
fig = go.Figure(layout=layout)
for ref in list(m['REF_AREA'].unique()):
temp = m[m['REF_AREA']==ref].sort_values(by='TIME_PERIOD').copy()
fig.add_trace(go.Scatter(x=temp['TIME_PERIOD'], y=temp['v'], name=ref,mode='lines+markers',marker=dict(size=5)))
fig.show()
In [ ]:
Fonte ISTAT¶
In [10]:
source_istat = {
"id": "ISTAT_NEW",
"api_id": "IT1",
"name": "Instituto Nationale di Statistica (IT)",
"documentation": "https://ec.europa.eu/eurostat/web/sdmx-web-services/rest-sdmx-2.1",
"url": "https://esploradati.istat.it/SDMXWS/rest",
"supports": {
"provisionagreement": False,
"structure-specific data": True
}
}
sdmx.add_source(source_istat, override=True)
istat = sdmx.Request('ISTAT_NEW', timeout=300)
istat.default_locale = "it"
flow_msg = istat.dataflow()
dataflows = pd.DataFrame(sdmx.to_pandas(flow_msg.dataflow)).reset_index(names='COD').rename(columns={0:'DESCR_IT'})
2024-09-18 18:08:44,085 pandasdmx.reader.sdmxml - DEBUG: Truncate sub-microsecond time in <Prepared>
In [11]:
dataflows[dataflows['DESCR_IT'].str.contains('abitaz', case=False)]
Out[11]:
| COD | DESCR_IT | |
|---|---|---|
| 267 | 143_497 | Prezzi delle abitazioni (Ipab) |
| 1503 | 27_474_DF_DCIS_SEPARAZIND1_6 | Assegnazione dell'abitazione |
| 1576 | 27_946_DF_DCIS_DIVORZIND1_6 | Assegnazione dell'abitazione |
| 1818 | 33_179 | Affollamento nell'abitazione |
| 1823 | 33_179_DF_DCCV_ABITAFFOLL_5 | Livello del reddito e abitazione in affitto o ... |
| 1825 | 33_225 | Spesa per l'abitazione |
| 1826 | 33_225_DF_DCCV_ABITSPESA_1 | Abitazione in affitto o di proprietà |
| 1832 | 33_290 | Titolo di godimento dell'abitazione (in affitt... |
| 1844 | 33_291_DF_DCCV_PROBLZONRES_2_5 | Livello del reddito e abitazione in affitto o ... |
| 1846 | 33_350 | Spesa per l'abitazione delle famiglie con comp... |
| 1847 | 33_350_DF_DCCV_ABITSPESA_STRA_1 | Spesa per l'abitazione delle famiglie con comp... |
| 1848 | 33_4 | Abitazione danneggiata, umida o poco luminosa |
| 1853 | 33_4_DF_DCCV_ABITPROBL_5 | Livello del reddito e abitazione in affitto o ... |
| 1899 | 34_217 | Famiglie che considerano un carico pesante alc... |
| 3234 | 82_87_DF_DCCV_AVQ_FAMIGLIE_16 | Spazi esterni e riscaldamento nell'abitazione |
| 3236 | 82_87_DF_DCCV_AVQ_FAMIGLIE_18 | Cambio dell'abitazione |
| 3237 | 82_87_DF_DCCV_AVQ_FAMIGLIE_19 | Spese, acqua e altri problemi dell'abitazione |
In [12]:
dataflows[dataflows['COD'].str.contains('143_497', case=False)]
Out[12]:
| COD | DESCR_IT | |
|---|---|---|
| 267 | 143_497 | Prezzi delle abitazioni (Ipab) |
| 268 | 143_497_DF_DCSP_IPAB_1 | Trimestrali dal 2010 (base 2015) |
| 269 | 143_497_DF_DCSP_IPAB_2 | Medie annue dal 2010 (base 2015) |
| 270 | 143_497_DF_DCSP_IPAB_3 | Pesi dal 2010 |
| 271 | 143_497_DF_DCSP_IPAB_4 | Trimestrali dal 2010 al 2016 (base 2010) |
| 272 | 143_497_DF_DCSP_IPAB_5 | Medie annue dal 2010 al 2016 (base 2010) |
Prezzi delle abitazioni (Ipab)¶
In [13]:
cod = '143_497'
#cod = '143_497_DF_DCSP_IPAB_2'
In [14]:
exr_msg = istat.dataflow(cod)
exr_flow = exr_msg.dataflow[cod]
dsd = exr_flow.structure
dims = dict()
for dimension in dsd.dimensions:
if dimension != 'TIME_PERIOD':
dims[dimension] = sdmx.to_pandas(dsd.dimensions.get(dimension).local_representation.enumerated).to_dict()['name']
In [15]:
#dims.keys()
In [16]:
#dims['REF_AREA']['ITFG']
In [17]:
#dims['REF_AREA']['ITE43']
In [18]:
#dims['FREQ']
In [19]:
#dims['MEASURE']
In [20]:
#dims['PURCHASES_DWELLINGS']
In [21]:
#dims['DATA_TYPE']
In [22]:
key = {
'DATA_TYPE': '60',
'PURCHASES_DWELLINGS': 'ALL',
'MEASURE': '4',
'FREQ': 'A'
}
params = {
'startPeriod':'2010'
}
try:
data_msg = istat.data(cod,key=key,params=params)
data_df = pd.DataFrame(sdmx.to_pandas(data_msg)).reset_index()
#ref_area_list = list(data_df['REF_AREA'].unique())
#procoms = [element for element in ref_area_list if self.check_procom(element)]
#data_df = data_df[data_df['REF_AREA'].isin(procoms)]
# data_df['AGE_G'] = data_df['AGE'].map(age_dict)
# data_df['SEX'] = data_df['SEX'].map(sex_dict)
except Exception as err:
print(err)
for field in dims.keys():
data_df[field] = data_df[field].map(dims[field])
2024-09-18 18:08:58,616 pandasdmx.reader.sdmxml - INFO: Use supplied dsd=… argument for non–structure-specific message
In [23]:
data_df = data_df[['REF_AREA','TIME_PERIOD','value']].copy()
data_df= data_df[data_df['REF_AREA'].isin(['Italy', 'Torino', 'Milano', 'Roma', 'Mezzogiorno'])].copy()
In [24]:
layout = go.Layout(title='Indice di compravendita delle abitazioni, 2010-2023, base 2010')
fig = go.Figure(layout=layout)
for ref in list(data_df['REF_AREA'].unique()):
temp = data_df[data_df['REF_AREA']==ref].sort_values(by='TIME_PERIOD').copy()
times = list(temp['TIME_PERIOD'].unique())
base_value = temp[temp['TIME_PERIOD']==times[0]]['value'].values[0]
diff = base_value-100
temp['value'] = temp['value'] - diff
fig.add_trace(go.Scatter(x=temp['TIME_PERIOD'], y=temp['value'], name=ref,mode='lines+markers',marker=dict(size=5)))
fig.show()
In [25]:
dataflows[dataflows['COD'].str.contains('32_292', case=False)]
Out[25]:
| COD | DESCR_IT | |
|---|---|---|
| 1801 | 32_292 | Reddito netto |
| 1802 | 32_292_DF_DCCV_REDNETFAMFONTERED_1 | Ampiezza della famiglia |
| 1803 | 32_292_DF_DCCV_REDNETFAMFONTERED_2 | Tipologia familiare |
| 1804 | 32_292_DF_DCCV_REDNETFAMFONTERED_3 | Minori in famiglia |
| 1805 | 32_292_DF_DCCV_REDNETFAMFONTERED_4 | Anziani in famiglia |
| 1806 | 32_292_DF_DCCV_REDNETFAMFONTERED_5 | Sesso del principale percettore |
| 1807 | 32_292_DF_DCCV_REDNETFAMFONTERED_6 | Classe di età del principale percettore |
| 1808 | 32_292_DF_DCCV_REDNETFAMFONTERED_7 | Titolo di studio del principale percettore |
| 1809 | 32_292_DF_DCCV_REDNETFAMFONTERED_8 | Condizione professionale del principale percet... |
| 1810 | 32_292_DF_DCCV_REDNETFAMFONTERED_9 | Regioni e tipo di comune |
Reddito medio (Irpef)¶
In [26]:
dataflows[dataflows['DESCR_IT'].str.contains('irpef', case=False)]
Out[26]:
| COD | DESCR_IT | |
|---|---|---|
| 1725 | 30_1008 | Reddito delle persone fisiche (Irpef) - comuni |
In [27]:
#cod = '30_1008'
cod = '32_292_DF_DCCV_REDNETFAMFONTERED_9'
In [28]:
exr_msg = istat.dataflow(cod)
exr_flow = exr_msg.dataflow[cod]
dsd = exr_flow.structure
dims = dict()
for dimension in dsd.dimensions:
if dimension != 'TIME_PERIOD':
dims[dimension] = sdmx.to_pandas(dsd.dimensions.get(dimension).local_representation.enumerated).to_dict()['name']
2024-09-18 18:09:06,242 pandasdmx.reader.sdmxml - DEBUG: Truncate sub-microsecond time in <Prepared>
In [29]:
dims.keys()
Out[29]:
dict_keys([<Dimension FREQ>, <Dimension REF_AREA>, <Dimension DATA_TYPE>, <Dimension MEASURE>, <Dimension IMPUTED_RENTS>, <Dimension FAM_MAIN_INCOME_SOURCE>, <Dimension NUMBER_HOUSEHOLD_COMP>, <Dimension HOUSEHOLD_TYPOLOGY>, <Dimension NUMB_OF_CHILDREN>, <Dimension NUMB_OF_ELDERLY>, <Dimension SEX_MAIN_PERCEPTOR>, <Dimension AGE_MAIN_EARNIER>, <Dimension EDU_LEV_MAIN_EARN>, <Dimension LABPROF_STATUS_C_MAIN_EARNER>])
In [30]:
dims['FAM_MAIN_INCOME_SOURCE']
Out[30]:
{'1': 'employee income',
'2': 'self-employed income',
'3': 'public transfers income',
'4': 'other type',
'9': 'total'}
In [31]:
dims['IMPUTED_RENTS']
Out[31]:
{'1': 'including imputed rents', '2': 'not including imputed rents'}
In [32]:
dims['DATA_TYPE']
Out[32]:
{'FAMIGLIE_POV': 'Poor households',
'INCID_POVASS_FAM': 'household absolute poverty incidence (% of households in absolute poverty)',
'FAM_POVASS': 'households in absolute poverty (% composition by residence area)',
'INTENS_POVASS_FAM': 'household absolute poverty intensity (% difference by the poverty threshold)',
'FAM_POVASS_VAL': 'households in absolute poverty (thousands)',
'FAM_VAL_PERC_POV': 'households by poverty line (% composition)',
'INCID_POVREL_FAM': 'household relative poverty incidence (% of households in relative poverty)',
'FAM_POVREL': 'households in relative poverty (% composition by residence area)',
'INTENS_POVREL_FAM': 'household relative poverty intensity (difference in % by the poverty threshold)',
'FAM_POVREL_VAL': 'households in relative poverty (thousands)',
'POV_ASSOLUTA': 'Absolute poverty',
'FAM_VAL_PERC': 'households (% composition)',
'FAM_VAL_PERC_QUA': 'households per expenditure quantile (% composition)',
'INDIVIDUI_POV': 'Poor individuals',
'INCID_POVASS_INDIV': 'individual absolute poverty incidence (% of persons living in households in absolute poverty)',
'INDIV_POVASS': 'individuals in absolute poverty (% composition by resident area)',
'INDIV_POVASS_VAL': 'individuals in absolute poverty (thousands)',
'INCID_POVREL_INDIV': 'individual relative poverty incidence (% of persons living in households in relative poverty)',
'INDIV_POVREL': 'individuals in relative poverty (% composition by resident area)',
'INDIV_POVREL_VAL': 'individuals in relative poverty (thousands)',
'POV_RELATIVA': 'Relative poverty',
'SOGLIA_POVREL': 'relative poverty threshold (monthly expenditure in euros)',
'SOGLIA_POVASS': 'absolute poverty threshold',
'DISUG_CONSUMI_GINI': 'Gini concentration index',
'DISUG_CONSUMI_ID': 's80/s20 quintile share ratio (average values)',
'FAM_COMPORT': 'households purchasing behaviour',
'FAM_LUOGHI': 'households purchasing place',
'FAM_SPEFF_ABB': 'households with expenditures for clothing and footwear',
'FAM_SPEFF_ABITAZ': 'households with expenditures for housing services',
'FAM_SPEFF_BENDUR': 'households with expenditures for durable goods',
'FAM_SPEFF_GIORN': 'households with expenditures for newspaper and books',
'FAM_SPEFF_PASTI': 'households with expenditures for catering services',
'FAM_SPEFF_SANIT': 'households with expenditures for health services',
'FAM_SPEFF_TRASPRIV': 'households with expenditures for private transport',
'FAM_SPEFF_TRASPUBB': 'households with expenditures for public transport',
'SPESA_EFF_ABB': 'households reporting expenditures on clothing and footwear',
'SPESA_EFF_ABITAZ': 'households reporting expenditures on housing services',
'SPESA_EFF_BENDUR': 'households reporting expenditures on durable goods',
'SPESA_EFF_FAM': 'households reporting expenditures on some items',
'SPESA_EFF_GIORN': 'households reporting expenditures on newspaper and books',
'SPESA_EFF_PASTI': 'households reporting expenditures on catering services',
'SPESA_EFF_SANIT': 'households reporting expenditures on health services',
'SPESA_EFF_TRASPRIV': 'households reporting expenditures on private transport',
'SPESA_EFF_TRASPUBB': 'households reporting expenditures on public transport',
'SPESA_MEDIA': 'household average monthly expenditure (in current euros)',
'SPESA_QUINTO': 'household expenditure quintile',
'ABITAZ_AFFOLL_MED': 'household crowding index (number of components of household per square meter)',
'ABITAZ_PROBLEMI': 'households with problems with the housing (percentage of household with the same characteristics)',
'ABITAZ_SPESA_M': 'housing average monthly expenditures (in euros)',
'ABITAZ_SPESA_REDD': 'housing average monthly expenditures (percentage of average monthly income)',
'DISUG_REDDNET_GINI': 'net family income distribution homogeneity',
'FAM_ARR_SPESA': 'households who have arrears on selected items (percent of households that bought that item)',
'FAM_FONTE_REDD': 'household per main income source (percentage values)',
'FAM_GIUD_CARICO': 'households who believe some housing expenses are burden (percentage of households facing expenses)',
'FAM_GIUD_FINEMESE': 'households per minimun income considered enough to make ends meet (percentage composition)',
'FAM_GIUD_PERCEP': "households who can and don't afford to arrive at the end of the month (percentage composition)",
'FAM_NO_BENDUR': 'households who cannot afford some durable goods (percent of households)',
'FAM_NO_SOLDI': 'households who do not have enough money for selected items (percent of households)',
'FAM_RISP': "households that can't afford to save (percent of households)",
'REDD_MEDIANO_FAM': 'annual median households income',
'REDD_MEDIO_FAM': 'annual average households income',
'REDD_QUINTO': 'households per fifth of equivalent household income (per 100 households with same characteristics)',
'FAM_SPESE_IMPR': "households that can't face unexpected expenses (percent of households)",
'FAM_NO_PERMETTERSI': 'households who do not afford to buy selected items (percent of household)',
'ZONA_RES_PROBLEMI': 'problems in the dwelling place',
'FAM_TITOLO_GODIM_ABITAZ': 'tenure status',
'REDD_QUINTO_STESSO': 'households per fifth of equivalent household income (per 100 households who belong to the same fifth of equivalent household income)',
'PCT_POV_ESCL': 'People at risk of poverty or social exclusion',
'PCT_RISK_POV': 'People at risk of poverty',
'PCT_SEV_MAT_DEP': 'People in conditions of severe material deprivation (4 out of 9 symptoms)',
'PCT_MAT_DEP': 'People in conditions of material deprivation (3 out of 9 symptoms)',
'PCT_LOW_INT': 'People in households with very low work intensity',
'PCT_POV_SOC_EXCL_EU2030': 'People at risk of poverty or social exclusion - Europe 2030',
'PCT_SEV_MAT_SOC_DEP_MOD13_EU2030': 'People in conditions of severe material and social deprivation (7 out of 13 symptoms) - Europe 2030',
'PCT_MAT_SOC_DEP_MOD13_EU2030': 'People in conditions of material e social deprivation (5 out of 13 symptoms) - Europe 2030',
'PCT_LOW_WORK_INT_EU2030': 'People in households with very low work intensity - Europa 2030'}
In [33]:
# data_msg = istat.data(cod)
# data_df = pd.DataFrame(sdmx.to_pandas(data_msg)).reset_index()
In [34]:
key = {
'DATA_TYPE': 'REDD_MEDIO_FAM',
'IMPUTED_RENTS': '2',
'FAM_MAIN_INCOME_SOURCE': '9'
}
params = {
'startPeriod':'2003'
}
try:
data_msg = istat.data(cod,key=key,params=params)
data_df = pd.DataFrame(sdmx.to_pandas(data_msg)).reset_index()
except Exception as err:
print(err)
for field in dims.keys():
data_df[field] = data_df[field].map(dims[field])
2024-09-18 18:09:08,466 pandasdmx.reader.sdmxml - DEBUG: Truncate sub-microsecond time in <Prepared> 2024-09-18 18:09:12,503 pandasdmx.reader.sdmxml - INFO: Use supplied dsd=… argument for non–structure-specific message
In [35]:
data_df = data_df[data_df['REF_AREA'].isin(['metropolitan area - centre',
'Italy', 'Lazio'])].copy()
data_df = data_df[['REF_AREA','TIME_PERIOD','value']].copy()
base_df = data_df[data_df['TIME_PERIOD']=='2003'].copy()
m = data_df.merge(base_df, on='REF_AREA', how='left')
m['v'] = m['value_x'] / m['value_y'] * 100
m['TIME_PERIOD'] = m['TIME_PERIOD_x'].astype(int)
In [36]:
layout = go.Layout(title='Reddito medio (Irpef) base 2003')
fig = go.Figure(layout=layout)
for ref in list(m['REF_AREA'].unique()):
temp = m[m['REF_AREA']==ref].sort_values(by='TIME_PERIOD').copy()
fig.add_trace(go.Scatter(x=temp['TIME_PERIOD'], y=temp['v'], name=ref,mode='lines+markers',marker=dict(size=5)))
fig.show()
In [ ]:
Famiglie in affitto per classe di reddito¶
In [37]:
#dataflows[(dataflows['DESCR_IT'].str.contains('affitto', case=False))].to_dict(orient='records')
In [38]:
#dataflows[(dataflows['COD'].str.contains('33_290', case=False))].to_dict(orient='records')
In [39]:
cod = '33_290_DF_DCCV_TITGODABIT_5'
In [40]:
exr_msg = istat.dataflow(cod)
exr_flow = exr_msg.dataflow[cod]
dsd = exr_flow.structure
dims = dict()
for dimension in dsd.dimensions:
if dimension != 'TIME_PERIOD':
dims[dimension] = sdmx.to_pandas(dsd.dimensions.get(dimension).local_representation.enumerated).to_dict()['name']
2024-09-18 18:09:18,835 pandasdmx.reader.sdmxml - DEBUG: Truncate sub-microsecond time in <Prepared>
In [41]:
dims.keys()
Out[41]:
dict_keys([<Dimension FREQ>, <Dimension REF_AREA>, <Dimension DATA_TYPE>, <Dimension MEASURE>, <Dimension TENURE_STATUS>, <Dimension FIFTH_EQUIV_HOUSE_INC>])
In [42]:
key = {
'TENURE_STATUS': '1'
}
params = {
'startPeriod':'2003'
}
try:
data_msg = istat.data(cod,key=key,params=params)
data_df = pd.DataFrame(sdmx.to_pandas(data_msg)).reset_index()
except Exception as err:
print(err)
for field in dims.keys():
data_df[field] = data_df[field].map(dims[field])
2024-09-18 18:09:21,434 pandasdmx.reader.sdmxml - DEBUG: Truncate sub-microsecond time in <Prepared>
2024-09-18 18:09:24,609 pandasdmx.reader.sdmxml - INFO: Use supplied dsd=… argument for non–structure-specific message
In [43]:
data_df = data_df[['FIFTH_EQUIV_HOUSE_INC','TIME_PERIOD','value']].copy()
In [44]:
data_df = data_df[data_df['FIFTH_EQUIV_HOUSE_INC']!='total'].copy()
In [45]:
data_df
Out[45]:
| FIFTH_EQUIV_HOUSE_INC | TIME_PERIOD | value | |
|---|---|---|---|
| 0 | first(lowest) | 2004 | 35.5 |
| 1 | first(lowest) | 2005 | 35.0 |
| 2 | first(lowest) | 2006 | 37.2 |
| 3 | first(lowest) | 2007 | 36.0 |
| 4 | first(lowest) | 2008 | 37.9 |
| ... | ... | ... | ... |
| 95 | fifth(highest) | 2019 | 7.2 |
| 96 | fifth(highest) | 2020 | 5.6 |
| 97 | fifth(highest) | 2021 | 7.1 |
| 98 | fifth(highest) | 2022 | 5.2 |
| 99 | fifth(highest) | 2023 | 5.3 |
100 rows × 3 columns
In [46]:
data_df['FIFTH_EQUIV_HOUSE_INC'].unique()
Out[46]:
array(['first(lowest)', 'second', 'third', 'fourth', 'fifth(highest)'],
dtype=object)
In [47]:
bars = []
for cls in data_df['FIFTH_EQUIV_HOUSE_INC'].unique():
temp = data_df[data_df['FIFTH_EQUIV_HOUSE_INC']==cls].copy()
bars.append(go.Bar(name=cls, x=temp['TIME_PERIOD'], y=temp['value']))
fig = go.Figure(data=bars)
# Change the bar mode
fig.update_layout(barmode='group')
fig.show()
In [ ]: