When using Bokeh for data visualization, encountering the error “ValueError: Out of range float values are not JSON compliant” can be significant. This error occurs because JSON, the format Bokeh uses to communicate data, does not support special float values like NaN or infinity. This can disrupt the rendering of visualizations, leading to incomplete or incorrect displays. Understanding and addressing this error is crucial for ensuring accurate and reliable data visualizations with Bokeh.
The error message “ValueError: Out of range float values are not JSON compliant” in Bokeh occurs when the library attempts to serialize a float value that is outside the range allowed by the JSON specification. JSON (JavaScript Object Notation) is a widely-used data format that does not support special float values like NaN
(Not a Number), Infinity
, or -Infinity
. When Bokeh tries to convert these values into JSON, it raises a ValueError
because these values are not compliant with the JSON standard.
JSON Specification: JSON does not support NaN
, Infinity
, or -Infinity
values. These values are common in Python and other programming languages but are not part of the JSON standard. When Bokeh tries to serialize a document containing these values, it fails because the JSON encoder cannot handle them.
Data Handling in Bokeh: Bokeh uses JSON to communicate between the Python backend and the JavaScript frontend. If the data contains out-of-range float values, the serialization process fails, causing the application to throw an error.
Serialization Process: During the serialization process, Bokeh converts its internal data structures into JSON format. If any of the data points contain out-of-range float values, the json.dumps
function in Python raises a ValueError
because it cannot represent these values in JSON.
Visualization Failure: The primary impact is that the visualization will not be rendered. Since Bokeh relies on JSON to transfer data to the browser, any failure in this process means that the plot or chart will not be displayed.
Data Integrity: If out-of-range float values are present in the data, it indicates potential issues with data integrity. These values might be the result of errors in data collection or processing, which need to be addressed to ensure accurate visualizations.
Error Handling: Developers need to implement error handling to check for and manage out-of-range float values before passing data to Bokeh. This can involve cleaning the data, replacing out-of-range values with valid ones, or using alternative representations.
To resolve this issue, you can preprocess your data to remove or replace NaN
, Infinity
, and -Infinity
values before passing it to Bokeh. This ensures that all float values are within the valid range for JSON serialization.
Here are common scenarios that lead to the ValueError: out of range float values are not JSON compliant
error in Bokeh, along with examples of code snippets that might trigger this error:
NaN (Not a Number) Values:
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
import numpy as np
data = {'x': [1, 2, 3], 'y': [4, np.nan, 6]}
source = ColumnDataSource(data)
p = figure()
p.line('x', 'y', source=source)
show(p)
Infinity Values:
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
import numpy as np
data = {'x': [1, 2, 3], 'y': [4, np.inf, 6]}
source = ColumnDataSource(data)
p = figure()
p.line('x', 'y', source=source)
show(p)
Out-of-Range Float Values:
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
data = {'x': [1, 2, 3], 'y': [4, 1e309, 6]} # 1e309 is out of range
source = ColumnDataSource(data)
p = figure()
p.line('x', 'y', source=source)
show(p)
Invalid Data Types:
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
data = {'x': [1, 2, 3], 'y': [4, complex(1, 1), 6]} # complex number is invalid
source = ColumnDataSource(data)
p = figure()
p.line('x', 'y', source=source)
show(p)
These scenarios often arise when the data being visualized contains values that are not JSON serializable, leading to the ValueError
.
Identify the Source of the Error:
NaN
, inf
, or -inf
values.print
statements or debugging tools to inspect the data.Replace Out-of-Range Values:
NaN
, inf
, or -inf
values with None
or a valid float.import numpy as np
data = np.nan_to_num(data, nan=None, posinf=None, neginf=None)
Validate Data Before Passing to Bokeh:
def validate_data(data):
if not np.isfinite(data).all():
raise ValueError("Data contains out-of-range float values.")
Convert Data to JSON-Compatible Format:
import json
data = json.dumps(data, allow_nan=False)
Update Bokeh Version:
pip install --upgrade bokeh
Use Safe Data Types:
ColumnDataSource
with numpy arrays instead of lists.from bokeh.models import ColumnDataSource
import numpy as np
source = ColumnDataSource({'x': np.array([]), 'y': np.array([])})
Handle Data in Custom JSON Encoder:
import json
class CustomJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, float) and (np.isnan(obj) or np.isinf(obj)):
return str(obj)
return super().default(obj)
json_data = json.dumps(data, cls=CustomJSONEncoder)
Check for Known Issues:
: GitHub Issue #5439
: GitHub Issue #6222
To avoid the “ValueError: out of range float values are not JSON compliant” error in Bokeh, follow these best practices:
Data Validation:
numpy
or pandas
to identify and handle NaN
or infinite values before passing data to Bokeh.import numpy as np
import pandas as pd
df = pd.DataFrame({'a': [1, 2, np.nan, np.inf]})
df = df.replace([np.inf, -np.inf], np.nan).dropna()
Handling Float Values:
round()
function to limit precision.df['a'] = df['a'].round(2)
Custom JSON Encoder:
import json
class CustomJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, float) and (obj != obj or obj == float('inf') or obj == float('-inf')):
return None
return super(CustomJSONEncoder, self).default(obj)
json.dumps(data, cls=CustomJSONEncoder)
Bokeh Configuration:
ColumnDataSource
to manage data and ensure it is JSON-compliant.from bokeh.models import ColumnDataSource
source = ColumnDataSource(data=dict(x=[1, 2, 3], y=[4, 5, 6]))
By implementing these practices, you can minimize the risk of
It’s essential to understand and address this issue for effective data visualization. The key points discussed include:
By following these best practices, developers can minimize the risk of encountering this error and create effective data visualizations with Bokeh.