最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Graph (histogram) is blank in Plotly Dash but displays correctly in Jupyter notebook - Stack Overflow

programmeradmin4浏览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.

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.

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!

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.

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.

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!

Share Improve this question asked Mar 18 at 4:47 AGAAGA 427 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 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)

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 fot to change the double backslashes back to single ones, like so:

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

发布评论

评论列表(0)

  1. 暂无评论