import dash
import dash_mantine_components as dmc
import pandas as pd
import dash_ag_grid as dag
from dash import _dash_renderer, callback, Input, Output, Dash
from dash import dcc, html
_dash_renderer._set_react_version("18.2.0")
app = Dash(
external_stylesheets=dmc.styles.ALL)
def load_data():
df = pd.read_csv('https://raw.githubusercontent.com/SmartDvi/Air_Pollution/main/air-pollution.csv')
df1 = pd.read_csv('https://raw.githubusercontent.com/SmartDvi/Air_Pollution/main/air-poplution-extraction-data.csv')
df_melted = df.melt(id_vars=['Year'], var_name='City', value_name='PM2.5')
df_melted[['City', 'Country']] = df_melted['City'].str.split(', ', expand=True, n=1)
df_melted['Country'] = df_melted['Country'].fillna('Singapore')
# Categorize PM2.5 values
df_melted['AQI_Level'] = df_melted['PM2.5'].apply(categorize_pm25)
# Merge the two datasets
merged_df = pd.merge(df_melted, df1, on='City', how='left')
# Calculate yearly averages and anomalies
yearly_avg = merged_df.groupby('Year')['PM2.5'].mean().reset_index()
yearly_avg.columns = ['Year', 'Yearly_Avg_PM2.5']
merged_df = merged_df.merge(yearly_avg, on='Year', how='left')
merged_df['PM2.5_Anomaly'] = merged_df['PM2.5'] - merged_df['Yearly_Avg_PM2.5']
# Calculate percentage change in PM2.5
merged_df.sort_values(by=['City', 'Year'], inplace=True)
merged_df['PM2.5_Pct_Change'] = merged_df.groupby('City')['PM2.5'].pct_change() * 100
# Convert Year to string for dropdown use
merged_df['Year'] = merged_df['Year'].astype(str)
return merged_df
def categorize_pm25(value):
if value <= 9.0:
return "Good"
elif 9.1 <= value <= 35.4:
return "Moderate"
elif 35.5 <= value <= 55.4:
return "Unhealthy for Sensitive Groups"
elif 55.5 <= value <= 150.4:
return "Unhealthy"
elif 150.5 <= value <= 225.4:
return "Very Unhealthy"
else:
return "Hazardous"
def group_aqi_level(aqi_level, specific_level):
"""
Function to group AQI levels into specific categories or 'Others'
"""
if aqi_level == specific_level:
return specific_level
else:
return 'Others'
def prepare_aqi_data(merged_df):
"""
Grouping the AQI level data for a donuts chart
"""
aqi_levels = ['Good', 'Moderate', 'Unhealthy', 'Unhealthy for Sensitive Groups', 'Hazardous']
aqi_data = {}
for level in aqi_levels:
merged_df['group_AQI'] = merged_df['AQI_Level'].apply(lambda x: group_aqi_level(x, level))
group_data = merged_df.groupby('group_AQI')['PM2.5'].sum().reset_index()
# Fetch the value for the specific AQI level and 'Others'
specific_value = group_data.loc[group_data['group_AQI'] == level, 'PM2.5'].values
others_value = group_data.loc[group_data['group_AQI'] == 'Others', 'PM2.5'].sum()
aqi_data[level] = {
'value': specific_value[0] if len(specific_value) > 0 else 0,
'others': others_value
}
return aqi_data
# Load the data and prepare AQI data
merged_df = load_data()
aqi_data = prepare_aqi_data(merged_df)
# Output a summary of AQI data (for debugging)
aqi_data
columnDefs=[
{'field': 'City', 'headerName': 'City'},
{'field': 'Country', 'headerName': 'Country'},
{
'field': 'PM2.5',
'headerName': 'PM2.5',
'valueFormatter': {"function": "d3.format('.2f')(params.value)"},
'type': 'rightAligned'
},
{
'field': 'PM2.5_Anomaly',
'headerName': 'PM2.5 Anomaly',
'valueFormatter': {"function": "d3.format('.2f')(params.value)"}, # Format to two decimal places
'type': 'rightAligned'
},
{
'field': 'PM2.5_Pct_Change',
'headerName': 'PM2.5 % Change',
'valueFormatter': {"function": "d3.format('.1f')(params.value) + '%'"},
'type': 'rightAligned'
},
{
'field': 'Yearly_Avg_PM2.5',
'headerName': 'Yearly_Avg_PM2.5',
'valueFormatter': {"function": "d3.format('.2f')(params.value)"}, # Format to two decimal places
'type': 'rightAligned'
}
]
grid = html.Div([
html.H1('Grid Page'),
dag.AgGrid(
id='grid_id',
columnDefs=columnDefs,
columnSize="autoSize",
rowData=merged_df.to_dict('records'),
defaultColDef={'editable': True, "filter": True, "floatingFilter": True},
dashGridOptions = {"suppressFieldDotNotation": True},
className="ag-theme-alpine-dark",
),
])
print(merged_df)
# developing app layout
app.layout = html.Div([
grid
]
)
if __name__ == "__main__":
app.run(debug=True, port=6084)
merged_df
print(columnDefs)