ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
https://github.com/plotly/plotly.py/blob/956ab2cd158f0d20b322aa49e2f717a56aa6b9e2/packages/python/plotly/plotly/basewidget.py#L857
I'm getting the following error from line 857 in basewidget.py:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
We're going to need some more context to be able to help you out at all here :) can you provide some minimal test case that shows how you're using the library such that this happens?
Thanks. Sorry for the late reply.
Here's the code to run in a Google Colab.
From the dropdown menu for "Add car data," select "car data." The error should then occur.
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from traitlets.config.application import deepcopy
from google.colab import output
output.enable_custom_widget_manager()
import datetime
from ipywidgets import widgets
import math
import random
from IPython.display import display
global car_weight_mpg
# Data points
car_weight_mpg = pd.DataFrame({
'x': [3.5, 3.69, 3.44, 3.43, 3.45, 4.34, 4.35, 4.31, 4.42, 3.85, 3.56, 3.61,
3.76, 3.09, 2.37, 2.83, 2.77, 2.59, 2.13, 1.83, 2.67, 2.43, 2.38, 2.23,
2.65, 4.62, 4.38, 4.38, 4.73, 2.13, 2.26, 2.23, 2.05, 2.63, 3.44, 3.33,
3.3, 3.29, 4.21, 4.46, 4.15, 4.1, 4.96, 4.75, 5.14, 2.96, 2.41, 3.28,
3.14, 2.22, 2.12, 2.07, 2.06, 1.77, 1.61, 1.83, 1.96, 2.28, 2.13, 2.25,
2.41, 2.23, 4.27, 4.38, 4.13, 4.13, 3.67, 4.63, 4.5, 4.46, 4.42, 2.33,],
'y': [18.0, 15.0, 18.0, 16.0, 17.0, 15.0, 14.0, 14.0, 14.0, 15.0, 15.0, 14.0,
15.0, 14.0, 24.0, 22.0, 18.0, 21.0, 27.0, 26.0, 25.0, 24.0, 25.0, 26.0,
21.0, 10.0, 10.0, 11.0, 9.0, 27.0, 28.0, 25.0, 25.0, 19.0, 16.0, 17.0,
19.0, 18.0, 14.0, 14.0, 14.0, 14.0, 12.0, 13.0, 13.0, 18.0, 22.0, 19.0,
18.0, 23.0, 28.0, 30.0, 30.0, 31.0, 35.0, 27.0, 26.0, 24.0, 25.0, 23.0,
20.0, 21.0, 13.0, 14.0, 15.0, 14.0, 17.0, 11.0, 13.0, 12.0, 13.0, 19.0,]})
# global variables
global points
global graph_objects
# figure to put all points and traces onto
ffigg = go.FigureWidget(data=(),
layout=go.Layout(title=dict(text="Loss"),
# xaxis=dict(range=[0,3]),
# yaxis=dict(range=[0,50]),
width=1000,
height=500))
# Get noise
noise = widgets.Dropdown(
options= [('No data', -1), ('Car data',1)],
value = -1,
description='Add car data',
disabled=False,
)
def get_mse():
values = loss_trace_points.values()
values = list(values)
single_values = []
for i in range(len(values)):
single_values.append(values[i][1])
squared_values = []
for l in single_values:
squared = (l[0] - l[1])**2
squared_values.append(squared)
result = round((sum(squared_values)/len(single_values)),2)
return result
weight = widgets.BoundedFloatText(
value=0,
min=-100,
max=100,
step=.1,
description='Weight:',
disabled=False
)
bias = widgets.BoundedFloatText(
value=0,
min=-100,
max=100,
step=.1,
description='Bias:',
disabled=False
)
loss_lines_on = widgets.Checkbox(
value=False,
description='Turn loss lines on',
disabled=False,
indent=False
)
mse = widgets.Text(
value='None',
description='MSE',
disabled=False,
)
# Get loss trace points when regression line moves
def get_loss_trace_points(points):
global loss_trace_points
loss_trace_points = {}
with ffigg.batch_update():
for i in range(len(points['x'])):
loss_trace_points['loss_trace_' + str(i)] = [
[points['x'][i], points['x'][i]],
[points['y'][i], new_weight*points['x'][i]+new_bias]
]
return loss_trace_points
def create_loss_traces(change):
global loss_trace_points
# Turn loss traces off
try:
with ffigg.batch_update():
if (loss_lines_on.get_interact_value() == False):
for i in range(len(loss_trace_points)):
ffigg.update_traces(selector=dict(name='loss_trace_' + str(i)), visible=False)
# Turn widget data off if traces are off
mse.value = 'None'
###
## Create loss traces
###
elif (loss_lines_on.get_interact_value()== True):
loss_trace_points = {}
with ffigg.batch_update():
# Get loss points
for i in range(len(points['x'])):
loss_trace_points['loss_trace_' + str(i)] = [
[points['x'][i], points['x'][i]],
[points['y'][i], weight.get_interact_value()*points['x'][i]+bias.get_interact_value()]
]
global loss_traces
loss_traces = {}
# Add loss traces to graph
for i in range(len(loss_trace_points)):
ffigg.add_trace(go.Scatter(x=loss_trace_points['loss_trace_' + str(i)][0],
y=loss_trace_points['loss_trace_'+ str(i)][1],
mode='lines+text',
showlegend=False,
name='loss_trace_' + str(i), line_color="#53adcb"))
# Add initial loss data to widget
mse.value = "{:.2f}".format(get_mse())
except Exception as e:
print(e)
pass
def add_data_points(change):
global points
# Clear figure data so traces are cleared each time
if (len(ffigg.data) != 0):
ffigg.data = ()
# Data when change is Zero
change_value = change['owner'].__dict__['_trait_values']['value']
if (type(change['owner']) == widgets.widget_selection.Dropdown):
# Clear data when "No Data" is selected
if (change_value == -1):
ffigg.data = ()
points = pd.DataFrame({'x':[], 'y': []})
# Data when change is car data
elif (change_value == 1):
ffigg.data = ()
# Car data
points = car_weight_mpg
else:
print("Turn trace lines on and off")
# Add points to loss_figure
with ffigg.batch_update():
ffigg.add_trace(go.Scatter(x=points['x'], y=points['y'], mode="markers",
name='Data', marker_size=12, marker_color='#ff726f'))
# Draw regression line
initial_weight = weight.get_interact_value()
initial_bias = bias.get_interact_value()
x_as_list = list(points['x'])
y_as_list = list(points['y'])
# Regression line data
# Get smallesst x and y to graph first point for regression line.
if (change_value != -1): # If there is any data
min_x = min(x_as_list)
max_x = max(x_as_list)
min_y = min(y_as_list)
max_y = max(y_as_list)
regression_line_data = pd.DataFrame({'x': [min_x, max_x],
'y': [(initial_weight*min_x) + initial_bias,
(initial_weight*max_x)+initial_bias]})
# Add regression line to loss_figure
with ffigg.batch_update():
ffigg.add_trace(go.Scatter(x=regression_line_data['x'],
y=regression_line_data['y'],
name='Interim model',
mode='lines',
line_color='green',
line_width=3))
# Check to see if loss traces should be on or off
create_loss_traces(change)
def move_regression_line(change):
global new_weight
global new_bias
global points
new_weight = weight.get_interact_value()
new_bias = bias.get_interact_value()
x_as_list = list(points['x'])
y_as_list = list(points['y'])
# Regression line data
# Get smallesst x and y to graph first point for regression line.
min_x = min(x_as_list)
max_x = max(x_as_list)
min_y = min(y_as_list)
max_y = max(y_as_list)
regression_line_data = pd.DataFrame({'x': [min_x, max_x],
'y': [(new_weight*min_x) + new_bias,
(new_weight*max_x)+ new_bias]})
with ffigg.batch_update():
print("Trying to move regression line")
ffigg.update_traces(x=regression_line_data['x'],
y=regression_line_data['y'],
selector=dict(name='Interim model'))
# Update loss line traces when regression line moves
if (len(ffigg.data)>2):
for i in range(len(loss_trace_points)):
ffigg.update_traces(selector=dict(name='loss_trace_'+ str(i)),
x=[points['x'][i], points['x'][i]],
y=[points['y'][i], weight.get_interact_value()*points['x'][i]+bias.get_interact_value()])
######
# Update loss widget values
######
if (loss_lines_on.get_interact_value()== True):
get_loss_trace_points(points)
mse.value = "{:.2f}".format(get_mse())
noise.observe(add_data_points)
loss_lines_on.observe(create_loss_traces)
bias.observe(move_regression_line)
weight.observe(move_regression_line)
display(
noise,
bias,
weight,
mse, loss_lines_on, ffigg)
Just checking in on this. :) Thanks!
Hey, sorry, this code is really long and complicated... are you able to find a more minimal test case that reproduces the bug?
Hey, sorry, this code is really long and complicated... are you able to find a more minimal test case that reproduces the bug?
Let me give a shorter test case to reproduce this bug.
First, below code is about using seaborn and matplotlib to plot a heatmap and it works.
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
correlation_matrix = pd.DataFrame(
{
"a": [1,2,3,4,5,6,7,8,9,10,11,12],
"b": [2,3,4,5,3,4,5,7,8,9,14,7],
"c": [7,7,7,5,3,14,5,7,15,9,14,7],
}
).corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt=".2f")
plt.title('Correlation Heatmap')
plt.xlabel('Variables')
plt.ylabel('Variables')
plt.show()
Then, let's try to use plotly to do the same thing.
import plotly.figure_factory as ff
import plotly.io as pio
import pandas as pd
correlation_matrix = pd.DataFrame(
{
"a": [1,2,3,4,5,6,7,8,9,10,11,12],
"b": [2,3,4,5,3,4,5,7,8,9,14,7],
"c": [7,7,7,5,3,14,5,7,15,9,14,7],
}
).corr()
fig = ff.create_annotated_heatmap(correlation_matrix.values,
x=correlation_matrix.columns.values,
y=correlation_matrix.index.values,
annotation_text = correlation_matrix.values,
colorscale='Viridis',
showscale=True)
fig.update_layout(title='Correlation Heatmap', xaxis=dict(title='Variables'), yaxis=dict(title='Variables'))
fig.show()
Above code raises an error.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[26], line 13
3 import pandas as pd
5 correlation_matrix = pd.DataFrame(
6 {
7 "a": [1,2,3,4,5,6,7,8,9,10,11,12],
(...)
10 }
11 ).corr()
---> 13 fig = ff.create_annotated_heatmap(correlation_matrix.values,
14 x=correlation_matrix.columns.values,
15 y=correlation_matrix.index.values,
16 annotation_text = correlation_matrix.values,
17 colorscale='Viridis',
18 showscale=True)
20 fig.update_layout(title='Correlation Heatmap', xaxis=dict(title='Variables'), yaxis=dict(title='Variables'))
22 fig.show()
File ~/anaconda3/lib/python3.11/site-packages/plotly/figure_factory/_annotated_heatmap.py:102, in create_annotated_heatmap(z, x, y, annotation_text, colorscale, font_colors, showscale, reversescale, **kwargs)
100 # Avoiding mutables in the call signature
101 font_colors = font_colors if font_colors is not None else []
--> 102 validate_annotated_heatmap(z, x, y, annotation_text)
104 # validate colorscale
105 colorscale_validator = ColorscaleValidator()
File ~/anaconda3/lib/python3.11/site-packages/plotly/figure_factory/_annotated_heatmap.py:31, in validate_annotated_heatmap(z, x, y, annotation_text)
26 if len(z[lst]) != len(annotation_text[lst]):
27 raise exceptions.PlotlyError(
28 "z and text should have the " "same dimensions"
29 )
---> 31 if x:
32 if len(x) != len(z[0]):
33 raise exceptions.PlotlyError(
34 "oops, the x list that you "
35 "provided does not match the "
36 "width of your z matrix "
37 )
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Reason
# Index(['a', 'b', 'c'], dtype='object')
if correlation_matrix.columns:
print("above condition raises error")
# array(['a', 'b', 'c'], dtype=object)
if correlation_matrix.columns.values:
print("above condition raises error")
# ['a', 'b', 'c']
if correlation_matrix.columns.to_list():
print("above condition works fine")
https://github.com/plotly/plotly.py/blob/956ab2cd158f0d20b322aa49e2f717a56aa6b9e2/packages/python/plotly/plotly/basewidget.py#L857
I'm getting the following error from line 857 in basewidget.py:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Here, if this input_val is not a simple list, error happens.
import numpy as np
input_val = np.array([1,2,3])
if input_val:
print("error happens in the condition")
To fix this, you can modify the condition to:
if input_val is not None:
print("this condition works fine")
In the code of plotly, many non-empty checks for the data are written incorrectly, using a shorthand that actually performs a check for true and false values. These check statements confuse the concept of None with truthiness.
@nicolaskruchten