Dash (and plotly) rounding large int64 values after the 16th digit

I’m having a problem with Dash dcc.Dropdown handling large int64 values. I’m using public data and the unique identifier is an integer that is 18 digits long (see examples in the attached screenshots). When I create an int64 array to use as a selection in dcc.Dropdown on Dash, it becomes rounded after the 16th digit. (I also see this behavior in plotly express when I create a hover item, and the only way I can fix it in px is to convert to string). However, in Dash, converting these values to another type such as string or float does not solve the rounding issue. If I change the type to float, I still see the same rounding behavior. If I change the type to string, the dropdown contains empty/no values.

I am using latest versions of Dash (2.13.0) and plotly express (5.17.0).

The first screenshot is the array of int64 values that I want to be in the dropdown (this is a numpy array with type int64). The second screenshot is how the values appear in the Dash dropdown.

Any advice on solving? Thanks.

Hi @shandran, can you please share the piece of code responsible for this behavior?
If I convert the unique IDs into strings, I don’t have rounding issues anymore, even in Dash.

Thanks for the quick reply. I uploaded a Jupyter notebook file, along with necessary data files in my debug folder on github: https://github.com/shandran/layer23-volume/tree/main/debug

(Sorry for the large csv data file sizes…)

The Jupyter notebook file demonstrates the rounding issue I’m having both in Dash and plotly express. (I have commented out code that loads an even larger dataset since if you ran that code, it would require you to download several hundred MBs of data files).

There are some (a lot!?) of additional code issues, due to my poor coding skills, but I wanted to solve the rounding issue first before moving on to fix the follow-on issues.

Let me know if you need anything else and thanks again for the help!
Shawn

@shandran the notebook is too big to display on GitHub.
Maybe you could only share the line(s) of code where you convert your int64 into strings as well as the dropdown component.

Sorry about that. Here is the code and screenshot showing the plotly express hover issue. It is solved by converting to a string (but my question is why can’t plotly express handle the 18 digit int64 without rounding at the 16th position – a 64 bit integer has 19 digits).

Here is a screenshot of the code:

Here is a screenshot of the hover function (showing that converting to a string is a work around):

Because plotly handles large int64 digits by rounding after the 16th position, it makes me think that Dash has the same issue handling these large 18 digit integers. Here is part of the code in question (omitting the code where the data arrays are derived):

from dash import Dash, dcc, Output, Input
import dash_bootstrap_components as dbc
import pandas as pd
import numpy as np
import os
import plotly.express as px
import plotly.graph_objects as go

components

app = Dash(name, external_stylesheets=[dbc.themes.LUX])
mytitle = dcc.Markdown(children=‘’)
mygraph = dcc.Graph(figure={})
dropdown = dcc.Dropdown(options=clean_complete.cellid.values,
value=str(clean_complete.cellid.values[0]), # initial value displayed when page first loads
clearable=False)

layout

app.layout = dbc.Container([
dbc.Row([
dbc.Col([mytitle], width=6)
], justify=‘center’),
dbc.Row([
dbc.Col([mygraph], width=12)
]),
dbc.Row([
dbc.Col([dropdown], width=6)
], justify=‘center’),
], fluid=True)

callback

@app.callback(
Output(mygraph, ‘figure’),
Output(mytitle, ‘children’),
Input(dropdown, ‘value’)
)

def update_graph(cellid): # function arguments come from the component property of the Input

fig = go.Figure(data=[
    go.Scatter3d(
        x=postsyn_xyz_dict.get('postsyn_xyz_dict_' + str(cellid))[:,0],
        y=postsyn_xyz_dict.get('postsyn_xyz_dict_' + str(cellid))[:,1],
        z=postsyn_xyz_dict.get('postsyn_xyz_dict_' + str(cellid))[:,2],
        mode="markers",
        marker=dict(size=2),
        showlegend=False)
])

fig.add_trace(
    go.Scatter3d(
        x=presyn_xyz_dict.get('presyn_xyz_dict_' + str(cellid))[:,0],
        y=presyn_xyz_dict.get('presyn_xyz_dict_' + str(cellid))[:,1],
        z=presyn_xyz_dict.get('presyn_xyz_dict_' + str(cellid))[:,2],
        mode="markers",
        marker=dict(size=3),
        showlegend=False)
)
  
return fig, '# '+cellid  # returned objects are assigned to the component property of the Output

run app

if name==‘main’:
app.run_server(debug=False, port=8044)

Here is the screenshot again for the resulting dropdown:

One quick additional note:

If I convert to str in the dcc.Dropdown line:
dropdown = dcc.Dropdown(options=str(clean_complete.cellid.values),

Here’s the resulting dropdown:

I think it’s not problem of Dash but pandas and you can easily solve it by set dtype of your dataframe when reading file by:

clean_complete = pd.read_csv("clean_and_complete_soma_ids_v185.csv", names=['cellid'], dtype={'cellid':str})

1 Like

Yes, thank you! That solved it. Such an easy fix and I never would have realized it was a pandas issue since I didn’t have the issue come up when using matplotlib, so I had assumed it was on the plotly side. Thanks.
Shawn

1 Like