Empty rows in dash Ag Grid Table

I develop a dash Ag Grid table but the numerical rows are not show, i have tired to fix it by print the data, columsdfs, and rowdata and they all printed data but still had empty row
this link to my code

import dash
import dash_mantine_components as dmc
import pandas as pd
import dash_ag_grid as dag
from dash import html, dcc, Input, Output, State, register_page, _dash_renderer, Dash
import dash_bootstrap_components as dbc



_dash_renderer._set_react_version("18.2.0")
app = Dash(__name__,
    external_stylesheets=dmc.styles.ALL)

task = """

### Project Task
Air quality around the globe has gone through significant ups and downs since the Industrial Revolution. Many factors affect the air that we breath such as the usage of coal power plants, clean air legislation, and automobile congestion.

`Week 36 of Figure-Friday` will dive into this topic with data 5 from the Air Quality Stripes project, which shows the concentration of particulate matter air pollution (PM2.5) in cities around the world.

##### Things to consider:
    - can you replicate the sample graph with Plotly?
    - can you improve the sample graph built?
    - would a different figure tell the data story better?
    - are you able to replicate or improve the app 3 built by the Air Quality Stripes project?

[data Source]()

    """


introduction = """
### Overview
This application is designed to provide comprehensive insights into Global air quality by analyzing PM2.5 (particulate matter with a diameter of less than 2.5 microns) levels across various cities and countries over multiple years. PM2.5 is a critical air pollutant that affects public health, and understanding its distribution and trends is essential for making informed decisions regarding environmental policies, public safety, and health regulations.

#### Key Features:
1. **Year and Country Selection**: Use the dropdowns to select specific years and countries, allowing for a focused view of air quality data in different regions.
2. **PM2.5 Gauge Indicator**: The dashboard features a real-time gauge that reflects the average PM2.5 concentration for the selected year, helping to quickly assess air quality levels.
3. **PM2.5 Scatter Chart**: Visualizes the PM2.5 concentrations across cities, allowing for city-to-city comparison in a given year.
4. **Yearly Trend Analysis**: The line chart tracks PM2.5 levels over time, with colors that change dynamically based on air quality levels. The average trend line gives a quick snapshot of whether air quality is improving or worsening.
5. **Mapbox Integration**: This feature allows for geographical visualization of PM2.5 levels and AQI categories across different cities. Users can see the spatial distribution of air quality, with city markers varying in size based on PM2.5 concentrations.

This dashboard combines visual data exploration with interactive components, making it an essential tool for environmental scientists, policymakers, and the public to monitor air quality trends, identify high-risk areas, and track progress toward cleaner air.




"""



def load_data():
    df = pd.read_csv('C:\\Users\\Moritus Peters\\Downloads\\air-pollution.csv')
    df1 = pd.read_csv('C:\\Users\\Moritus Peters\\Downloads\\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
print(merged_df)


# Retrive column names


# Generate column definition for AG Grid

        
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},
        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)

Hi @Moritus

Thanks for posting a complete example with data - it made it easy to see the problem.

With the grid, dots in the field names allows you to access nested data. If that is not your intent, and the name simply has a dot, add:

dag.AgGrid(
    dashGridOptions = {"suppressFieldDotNotation": True}
    # other
)

More info here:

thanks @AnnMarieW it worked

1 Like