Hello @samorouji,
As far as the getRowStyle
, you need to do this:
getRowStyle = {
"styleConditions": [
{
"condition": "params.data['yoy%'] > 0",
"style": {"backgroundColor": "green"},
},
{
"condition": "params.data['yoy%'] < 0",
"style": {"backgroundColor": "red"},
},
],
"defaultStyle": {"backgroundColor": "grey", "color": "white"},
}
%
is a reserved character, so thats why you can just do params.data.yoy%
Here is a modified version to make it work, however, I can see that the requests are going through to query your data, I cannot confirm the data coming back from the api:
import dash
from dash import dcc, html, dash_table, callback, Input, Output, State, no_update, Dash
import plotly.express as px
import pandas as pd # Data science library for data manipulation with data frames
import requests
from markupsafe import escape
import dash_ag_grid as dag
# Fred API Calls (Restful API structure)
# +- create an api call that gets updated data PPI and calculates the YoY change from exactly one year ago so this dashboard has accurate info
API_KEY = 'blurred out'
app = Dash(__name__)
def get_fred_data(series_id):
print(series_id)
# url = f'https://api.stlouisfed.org/fred/series/observations?series_id={series_id}&api_key={API_KEY}&file_type=json'
# response = requests.get(url)
# if response.status_code != 200:
# print(f"Failed to fetch data from FRED API. Status Code: {response.status_code}")
# return pd.DataFrame() # Return an empty DataFrame
# data = response.json()
# if 'observations' not in data:
# print("No 'observations' key in API response.")
# print(data) # Print the full API response to see its structure
# return pd.DataFrame() # Return an empty DataFrame
# # pandas with dataframes -- study up but this is the basics i need for now
# df = pd.DataFrame(data['observations'])
# df['date'] = pd.to_datetime(df['date'])
# df['value'] = pd.to_numeric(df['value'])
return no_update
# indices and categories
indices = [
{'label': 'Construction For Government', 'value': 'WPUFD432'},
{'label': 'Electrical Contractors Non-Residential', 'value': 'PCU23821X23821X'},
{'label': 'Multi Family', 'value': 'WPUIP231120'},
{'label': 'Engineering Services', 'value': 'WPU4532'},
{'label': 'Cement', 'value': 'WPU1322'},
]
# kinda useless right now - not organizing by dropdown
category = ['Consumer, Producer & Construction prices',
'new, repair & maintenance work by subcontractors',
'inputs to construction industries',
'services important to construction',
'processed goods important to construction',
'unprocessed goods important to construction',
'total compensation, wages & salaries']
# grid Columns and Rows
column_defs = [
{'headerName': "Category", 'field': 'category', 'sortable': True, 'filter': True, "checkboxSelection": True,
"headerCheckboxSelection": True, },
{'headerName': "Indice", 'field': 'indice', 'sortable': True, 'filter': True},
{'headerName': "Ticker", 'field': 'ticker', 'sortable': True, 'filter': True},
{'headerName': "PPI", 'field': 'ppi', 'sortable': True, 'filter': True},
{'headerName': "YOY%", 'field': "yoy%", 'sortable': True, 'filter': True},
{'headerName': "Date", 'field': 'date', 'sortable': True, 'filter': True, "filter": "agDateColumnFilter",
"filterValueGetter": {"function": "d3.timeParse('%d/%m/%Y')(params.data.date)"}, "filterParams": {
"browserDatePicker": True,
"minValidYear": 2000,
"maxValidYear": 2021,
},
},
]
row_data = [
{'category': "Consumer, Producer & Construction prices", "indice": "Construction For Government",
"ticker": "WPUFD432", "ppi": 167.184, "yoy%": -0.75, "date": "1/24/2024"},
{'category': "new, repair & maintenance work by subcontractors", "indice": "Electrical Contractors Non-Residential",
"ticker": "PCU23821X23821X", "ppi": 167.129, "yoy%": -4.70, "date": "1/24/2024"},
{'category': "inputs to construction industries", "indice": "Multi Family", "ticker": "WPUIP231120", "ppi": 149.403,
"yoy%": 2.09, "date": "1/24/2024"},
{'category': "services important to construction", "indice": "Engineering Services", "ticker": "WPU4532",
"ppi": 136.993, "yoy%": 1.98, "date": "1/25/2024"},
{'category': "processed goods important to construction", "indice": "Cement", "ticker": "WPU1322", "ppi": 351.768,
"yoy%": 8.17, "date": "1/24/2024"},
{'category': "Consumer, Producer & Construction prices", "indice": "Construction For Government",
"ticker": "WPUFD432", "ppi": 167.184, "yoy%": -0.75, "date": "1/24/2024"},
{'category': "new, repair & maintenance work by subcontractors", "indice": "Electrical Contractors Non-Residential",
"ticker": "PCU23821X23821X", "ppi": 167.129, "yoy%": -4.70, "date": "1/24/2024"},
{'category': "inputs to construction industries", "indice": "Multi Family", "ticker": "WPUIP231120", "ppi": 149.403,
"yoy%": 2.09, "date": "1/24/2024"},
{'category': "services important to construction", "indice": "Engineering Services", "ticker": "WPU4532",
"ppi": 136.993, "yoy%": 1.98, "date": "1/25/2024"},
{'category': "processed goods important to construction", "indice": "Cement", "ticker": "WPU1322", "ppi": 351.768,
"yoy%": 8.17, "date": "1/24/2024"},
{'category': "Consumer, Producer & Construction prices", "indice": "Construction For Government",
"ticker": "WPUFD432", "ppi": 167.184, "yoy%": -0.75, "date": "1/24/2024"},
{'category': "new, repair & maintenance work by subcontractors", "indice": "Electrical Contractors Non-Residential",
"ticker": "PCU23821X23821X", "ppi": 167.129, "yoy%": -4.70, "date": "1/24/2024"},
{'category': "inputs to construction industries", "indice": "Multi Family", "ticker": "WPUIP231120", "ppi": 149.403,
"yoy%": 2.09, "date": "1/24/2024"},
{'category': "services important to construction", "indice": "Engineering Services", "ticker": "WPU4532",
"ppi": 136.993, "yoy%": 1.98, "date": "1/25/2024"},
{'category': "processed goods important to construction", "indice": "Cement", "ticker": "WPU1322", "ppi": 351.768,
"yoy%": 8.17, "date": "1/24/2024"},
]
# +-function for row color change for yoy% change. If positive green, negative red.
getRowStyle = {
"styleConditions": [
{
"condition": "params.data['yoy%'] > 0",
"style": {"backgroundColor": "green"},
},
{
"condition": "params.data['yoy%'] < 0",
"style": {"backgroundColor": "red"},
},
],
"defaultStyle": {"backgroundColor": "grey", "color": "white"},
}
@app.callback(
Output('central-graph', 'figure'),
Input('dash-griddy', 'selectedRows'), # do i need virtualRows also for input?
prevent_initial_call=True
)
def update_graph(selected_row):
if not selected_row:
return {'data': [], 'layout': {'title': 'Construction For Government',
'xaxis': {'title': 'Date', 'hoverformat': ''},
'yaxis': {'title': 'PPI', 'hoverformat': ''},
"colorway": [],
"hovermode": "x",
'hoverlabel': {
'bgcolor': "white",
'font_size': 25,
'font_family': "Helvetica"
},}}
ticker = selected_row[0]['ticker'] # +-First selected row's ticker
df = get_fred_data(ticker) # Fetches data from API
return df
# I need to create a function that takes the ticker, calls get_fred_data('ticker), then change that variable['date'] for x value,
# variable['value'] for y ^^^ what above should do
color_map = {
'WPUFD432': 'red',
'PCU23821X23821X': 'orange',
'WPUIP231120': 'yellow',
'WPU4532': 'green',
'WPU1322': 'blue',
}
line_color = color_map.get(ticker, 'black') # Get color- black by default
# now put ticker
figure = {
'data': [
{
'x': df['date'],
'y': df['value'],
'type': 'line',
'name': 'Construction For Government',
'line': {'width': 3},
'hovertemplate': '<br><b>%{x}: </b>%{y:.2f}<extra></extra>',
}
],
'layout': {
'title': 'Construction For Government',
'xaxis': {'title': 'Date', 'hoverformat': ''},
'yaxis': {'title': 'PPI', 'hoverformat': ''},
"colorway": [line_color],
"hovermode": "x",
'hoverlabel': {
'bgcolor': "white",
'font_size': 25,
'font_family': "Helvetica"
},
}
},
return figure
# instead of these functions create callback to input said data frame to call to fred api to gather data
CONSTRUCTION4GVMT_df = get_fred_data('WPUFD432')
ELECRICALCONTRACTORSNONRESBUILDINGWORK_df = get_fred_data('PCU23821X23821X')
MULTIFAM_df = get_fred_data('WPUIP231120')
ENGRSERVICES_df = get_fred_data('WPU4532')
CEMENT_df = get_fred_data('WPU1322')
# Layout to be Displayed on app.py container
layout = html.Div(
[
# graph starts blank, so when the callback updates plots are put on it
dcc.Graph(
figure={
'data': [
{
# 'x': CONSTRUCTION4GVMT_df['date'],
# 'y': CONSTRUCTION4GVMT_df['value'],
'line': {'width': 3}, # keep this
'hovertemplate': '<br><b>%{x}: </b>%{y:.2f}<extra></extra>', # keep this
}
],
# change normal layout here ^ put None for values above or comment it out
'layout': {
'title': 'Universal Graph Title',
'xaxis': {'title': 'Date', 'hoverformat': ''},
'yaxis': {'title': 'PPI', 'hoverformat': ''},
"colorway": ['black'],
"hovermode": "x",
'hoverlabel': {
'bgcolor': "white",
'font_size': 25,
'font_family': "Helvetica"
},
}
},
id='central-graph',
className="graph-container"
),
# data grid
html.Div(
dag.AgGrid(
id="dash-griddy", # use this id for callbacks to update the graph when check boxes are selected
columnDefs=column_defs,
rowData=row_data,
columnSize="responsiveSizeToFit",
defaultColDef={"filter": True},
getRowStyle=getRowStyle,
dashGridOptions={
"rowSelection": "multiple",
'suppressRowClickSelection': True,
'suppressMovableColumns': True,
},
),
className="ag-grid-div"
)
],
)
app.layout = layout
if __name__ == '__main__':
app.run_server(debug=True)
Obviously, uncomment the api call, to continue troubleshooting you should be printing at different increments.