0

I am trying to create a Dash app but the graph I want to display is blank. It shows up exactly how I want it to in my Jupyter notebook, but it is blank in my Dash app.

graph displaying properly, with 7 bars for each category

Here is the code used in the notebook to get the graph:

import kagglehub
import pandas as pd
import matplotlib.pyplot as plt
import math
import re
import plotly.graph_objects as go
import plotly.express as px

def get_class(text):
    x = re.findall("\\n (\w*) Class: (\w*) \\n", text)
    if x :
        return(list(x[0]))
    else:
        return ["None", "None"]
def get_class_type(text):
    return get_class(text)[0]
def get_class_spec(text):
    return get_class(text)[1]
def get_series(scp_code):
    num = int(scp_code[4:])
    return math.ceil(num/1000)

path = kagglehub.dataset_download("czzzzzzz/scp1to7")
df = pd.read_csv(f"{path}/scp6999.csv")
# I replaced the two lines above by
# df = pd.read_csv("<insert path on my machine>/scp6999.csv")
# to avoid repeatedly asking Kaggle for the dataset, but this is how I
# initially got it

df["class type"] = df["text"].apply(get_class_type)
df["class"] = df["text"].apply(get_class_spec)
df["series"] = df["code"].apply(get_series)

primary_classes=["Safe", "Euclid", "Keter"]
primary_classes_df = df[df["class"].isin(primary_classes)]
class_counts = primary_classes_df.groupby(["class", "series"]).count().reset_index()

fig = px.histogram(class_counts, x="class", y="code", color="series", color_discrete_sequence=px.colors.sequential.Plasma_r, barmode="group",
                  title="Distribution of SCPs by containment class by series")
fig.update_xaxes(categoryorder="array", categoryarray=primary_classes)
fig.update_layout(yaxis_title="")
fig.update_traces(hovertemplate='Total SCPs: %{y}<extra></extra>')
fig.show()

In Dash, I tried creating the same graph with the same code, replacing of course the last line by

graph1 = dcc.Graph(
    figure = fig,
    className="border",
)

I kept getting the following error:

ValueError: Cannot accept list of column references or list of columns for both `x` and `y`

So I decided to create list variables instead of using DataFrame columns. I tested it with Dash.

x_data = class_counts["class"].tolist()
y_data = class_counts["code"].tolist()
color_data = class_counts["series"].tolist()
fig = px.histogram(class_counts, x=x_data, y=y_data, color=color_data, 
    color_discrete_sequence=px.colors.sequential.Plasma_r, barmode="group",
    title="Distribution of SCPs by containment class by series")

The good news is that it no longer throws an error. The bad news is that I get a completely empty chart. It has a title and axes, but no bars. I checked, and the DataFrame is not empty: it has 21 rows as expected.

a graph with a title and axes, but no data, it is completely blank

I would love to know why it is blank and how I can make it look like the graph I get in Jupyter. Thanks in advance for your help!

2 Answers 2

1

It may be related to how you initialise the Dash app. On my end, the plot displays correctly when I structure like this.

import dash
from dash import dcc, html

# Initialize Dash app
app = dash.Dash(__name__)

app.layout = html.Div(children=[
    html.H1("SCP Containment Class Distribution"),
    dcc.Graph(id="scp_chart", figure=fig)
])

if __name__ == "__main__":
    app.run(debug=True)

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for trying it. It helped me isolate the issue. It turns out the problem wasn’t with Dash at all!
0

TLDR: I was looking for the problem in the wrong place, I was stuck in a rut, but reading nrmzmh’s response unstuck me and I found my stupid mistake.

So I was so focused on the fact that I’m learning Dash and I’m not familiar with it that I was staring at the code to create graphs in Dash and not getting what went wrong. Thanks to nrmzmh I realized that wasn’t the problem.

So in Jupyter I had this:

re.findall("\\n (\w*) Class: (\w*) \\n", text)

And all my testing told me the data was fine, because it was.

But then, as a .py script, it didn’t handle the escape characters well, so I wrote this instead:

re.findall(r"\\n (\w*) Class: (\w*) \\n", text)

So I added the "r" to make it a raw string but forgot to change the double backslashes back to single ones, like so:

re.findall(r"\n (\w*) Class: (\w*) \n", text)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.