ValueError: Invalid element(s) received for the 'data' property

Question:

I encounter an issue with plotly. I would like to display different figures but, somehow, I can’t manage to achieve what I want.

I created 2 sources of data:

from plotly.graph_objs.scatter import Line
import plotly.graph_objs as go

trace11 = go.Scatter(
    x = [0, 1, 2],
    y = [0, 0, 0],
    line = Line({'color': 'rgb(0, 0, 128)', 'width': 1})
)

trace12 = go.Scatter(
    x=[0, 1, 2],
    y=[1, 1, 1],
    line = Line({'color': 'rgb(128, 0, 0)', 'width': 1})
)

trace21 = go.Scatter(
    x = [0, 1, 2],
    y = [0.5, 0.5, 0.5],
    line = Line({'color': 'rgb(0, 0, 128)', 'width': 1})
)

trace22 = go.Scatter(
    x=[0, 1, 2],
    y=[1.5, 1.5, 1.5],
    line = Line({'color': 'rgb(128, 0, 0)', 'width': 1})
)

data1 = [trace11, trace12]
data2 = [trace21, trace22]

Then, I created a subplot with 1 row and 2 columns and tried to add this data to the subplot:

from plotly import tools
fig = tools.make_subplots(rows=1, cols=2)
fig.append_trace(data1, 1, 1)
fig.append_trace(data2, 1, 2)
fig.show()

That resulted in the following error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-ba20e4900d41> in <module>
      1 from plotly import tools
      2 fig = tools.make_subplots(rows=1, cols=2)
----> 3 fig.append_trace(data1, 1, 1)
      4 fig.append_trace(data2, 1, 2)
      5 fig.show()

~Anaconda3libsite-packagesplotlybasedatatypes.py in append_trace(self, trace, row, col)
   1797         )
   1798 
-> 1799         self.add_trace(trace=trace, row=row, col=col)
   1800 
   1801     def _set_trace_grid_position(self, trace, row, col, secondary_y=False):

~Anaconda3libsite-packagesplotlybasedatatypes.py in add_trace(self, trace, row, col, secondary_y)
   1621             rows=[row] if row is not None else None,
   1622             cols=[col] if col is not None else None,
-> 1623             secondary_ys=[secondary_y] if secondary_y is not None else None,
   1624         )
   1625 

~Anaconda3libsite-packagesplotlybasedatatypes.py in add_traces(self, data, rows, cols, secondary_ys)
   1684 
   1685         # Validate traces
-> 1686         data = self._data_validator.validate_coerce(data)
   1687 
   1688         # Set trace indexes

~Anaconda3libsite-packages_plotly_utilsbasevalidators.py in validate_coerce(self, v, skip_invalid)
   2667 
   2668             if invalid_els:
-> 2669                 self.raise_invalid_elements(invalid_els)
   2670 
   2671             v = to_scalar_or_list(res)

~Anaconda3libsite-packages_plotly_utilsbasevalidators.py in raise_invalid_elements(self, invalid_els)
    296                     pname=self.parent_name,
    297                     invalid=invalid_els[:10],
--> 298                     valid_clr_desc=self.description(),
    299                 )
    300             )

ValueError: 
    Invalid element(s) received for the 'data' property of 
        Invalid elements include: [[Scatter({
    'line': {'color': 'rgb(0, 0, 128)', 'width': 1}, 'x': [0, 1, 2], 'y': [0, 0, 0]
}), Scatter({
    'line': {'color': 'rgb(128, 0, 0)', 'width': 1}, 'x': [0, 1, 2], 'y': [1, 1, 1]
})]]

    The 'data' property is a tuple of trace instances
    that may be specified as:
      - A list or tuple of trace instances
        (e.g. [Scatter(...), Bar(...)])
      - A single trace instance
        (e.g. Scatter(...), Bar(...), etc.)
      - A list or tuple of dicts of string/value properties where:
        - The 'type' property specifies the trace type
            One of: ['area', 'bar', 'barpolar', 'box',
                     'candlestick', 'carpet', 'choropleth',
                     'choroplethmapbox', 'cone', 'contour',
                     'contourcarpet', 'densitymapbox', 'funnel',
                     'funnelarea', 'heatmap', 'heatmapgl',
                     'histogram', 'histogram2d',
                     'histogram2dcontour', 'image', 'indicator',
                     'isosurface', 'mesh3d', 'ohlc', 'parcats',
                     'parcoords', 'pie', 'pointcloud', 'sankey',
                     'scatter', 'scatter3d', 'scattercarpet',
                     'scattergeo', 'scattergl', 'scattermapbox',
                     'scatterpolar', 'scatterpolargl',
                     'scatterternary', 'splom', 'streamtube',
                     'sunburst', 'surface', 'table', 'treemap',
                     'violin', 'volume', 'waterfall']

        - All remaining properties are passed to the constructor of
          the specified trace type

        (e.g. [{'type': 'scatter', ...}, {'type': 'bar, ...}])

I mist be doing something wrong. What is weird is that my data seems correctly shaped since I can run the following code without any issue:

fig = go.Figure(data1)
fig.show()

I hope you can help me find a solution.

Thanks!

Asked By: barthelemy-simon

||

Answers:

I was running into a similar problem myself while doing the Interactive Python Dashboards with Plotly and Dash Udemy course and figured out how to get my code to work so I will post my problematic code and what ended up working for me so you can compare. Keep in mind I am not a programmer or computer scientist by trade so I can’t provide all the ins and out of what’s going on behind the scenes… Just what works for me.. Also, I literally got my code working while reviewing your code and noticed that we were both passing in lists, while other code that works for the append_trace() call does not pass in a list. I hope this helps.

First, tools.make_subplots() is deprecated based on my research of this issue, and the import of tools from plotly is not used anywhere in my code. I think you need to use:

from plotly.subplots import make_subplots

Next, I think I was simply using a list where it was inappropriate. Here is my original code that did not work:

import plotly.offline as pyo
import plotly.graph_objs as go
from plotly import tools
from plotly.subplots import make_subplots
import pandas as pd

df1 = pd.read_csv('Data/2010SantaBarbaraCA.csv')
df2 = pd.read_csv('Data/2010YumaAZ.csv')
df3 = pd.read_csv('Data/2010SitkaAK.csv')


trace1 = [go.Heatmap(x=df1['DAY'],
                   y=df1['LST_TIME'],
                   z=df1['T_HR_AVG'].values.tolist(),
                     zmin=5,
                     zmax=40)]  # z= cannot accept a pandas column, needs to be a list

trace2 = [go.Heatmap(x=df2['DAY'],
                   y=df2['LST_TIME'],
                   z=df2['T_HR_AVG'].values.tolist(),
                     zmin=5,
                     zmax=40)]  # z= cannot accept a pandas column, needs to be a list

trace3 = [go.Heatmap(x=df3['DAY'],
                   y=df3['LST_TIME'],
                   z=df3['T_HR_AVG'].values.tolist(),
                     zmin=5,
                     zmax=40)]  # z= cannot accept a pandas column, needs to be a list

# fig = tools.make_sublots(rows=1,
#                          columns=3,
#                          subplot_titles=['Santa Barbara CA','Yuma AZ', 'Sitka AK'],
#                          shared_yaxes=True)

fig = make_subplots(rows=1,
                cols=3,
                subplot_titles=['Santa Barbara CA', 'Yuma AZ', 'Sitka AK'],
                shared_yaxes=True)


# fig.append_trace(trace#, row#, column#)
fig.append_trace(trace1, row=1, col=1)
fig.append_trace(trace2, row=1, col=2)
fig.append_trace(trace3, row=1, col=3)

# data = [trace1, trace2, trace3]

# layout = go.Layout(title='Santa Barbara California Temperatures')

pyo.plot(fig)

Notice I had my trace#’s defined with brackets

trace1 = [go.Heatmap(x=df1['DAY'],
                   y=df1['LST_TIME'],
                   z=df1['T_HR_AVG'].values.tolist(),
                     zmin=5,
                     zmax=40)]

When I removed the brackets from each of my trace declarations my code worked. Here is my code that works:

import plotly.offline as pyo
import plotly.graph_objs as go
from plotly import tools
from plotly.subplots import make_subplots
import pandas as pd

df1 = pd.read_csv('Data/2010SantaBarbaraCA.csv')
df2 = pd.read_csv('Data/2010YumaAZ.csv')
df3 = pd.read_csv('Data/2010SitkaAK.csv')


trace1 = go.Heatmap(x=df1['DAY'],
                   y=df1['LST_TIME'],
                   z=df1['T_HR_AVG'].values.tolist(),
                     zmin=5,
                     zmax=40)  # z= cannot accept a pandas column, needs to be a list

trace2 = go.Heatmap(x=df2['DAY'],
                   y=df2['LST_TIME'],
                   z=df2['T_HR_AVG'].values.tolist(),
                     zmin=5,
                     zmax=40)  # z= cannot accept a pandas column, needs to be a list

trace3 = go.Heatmap(x=df3['DAY'],
                   y=df3['LST_TIME'],
                   z=df3['T_HR_AVG'].values.tolist(),
                     zmin=5,
                     zmax=40)  # z= cannot accept a pandas column, needs to be a list

# fig = tools.make_sublots(rows=1,
#                          columns=3,
#                          subplot_titles=['Santa Barbara CA','Yuma AZ', 'Sitka AK'],
#                          shared_yaxes=True)

fig = make_subplots(rows=1,
                    cols=3,
                    subplot_titles=['Santa Barbara CA', 'Yuma AZ', 'Sitka AK'],
                    shared_yaxes=True)


# fig.append_trace(trace#, row#, column#)
fig.append_trace(trace1, row=1, col=1)
fig.append_trace(trace2, row=1, col=2)
fig.append_trace(trace3, row=1, col=3)

# data = [trace1, trace2, trace3]

# layout = go.Layout(title='Santa Barbara California Temperatures')

pyo.plot(fig)

I know you are using Scatter and I am using Heatmaps but I think your issue may be(apart from using tools for make_subplots()) that you are passing data1 and data2 into your append_trace() calls as lists, and I don’t think the append_trace() call likes this. I would suggest not passing in a list to the append_trace() call and seeing if that works. If it does then you may need to adjust your data variables to not be listed and go from there. I hope this helps.

Answered By: Evan Howington

The reason why you are getting an error it is because the function append_trace() is expecting a single trace in the form you’ve declared them. However, the graph object Figure has the function add_traces() with which you can pass the data parameter as a list with more than one trace.
Therefore, I suggest two simple solutions:

Solution 1: Append traces individually

from plotly.graph_objs.scatter import Line
import plotly.graph_objs as go
trace11 = go.Scatter(x = [0, 1, 2], y = [0, 0, 0],  line = Line({'color': 'rgb(0, 0, 128)', 'width': 1}))
trace12 = go.Scatter(x = [0, 1, 2], y = [1, 1, 1], line = Line({'color': 'rgb(128, 0, 0)', 'width': 1}))
trace21 = go.Scatter(x = [0, 1, 2], y = [0.5, 0.5, 0.5], line = Line({'color': 'rgb(0, 0, 128)', 'width': 1}))
trace22 = go.Scatter(x = [0, 1, 2], y = [1.5, 1.5, 1.5], line = Line({'color': 'rgb(128, 0, 0)', 'width': 1}))

from plotly.subplots import make_subplots
fig = make_subplots(rows=1, cols=2)
fig.append_trace(trace11, row=1, col=1)
fig.append_trace(trace12, row=1, col=1)
fig.append_trace(trace21, row=1, col=2)
fig.append_trace(trace22, row=1, col=2)
fig.show()

Solution 2: Use the function add_traces(data,rows,cols) instead

from plotly.graph_objs.scatter import Line
import plotly.graph_objs as go
trace11 = go.Scatter(x = [0, 1, 2], y = [0, 0, 0], line = Line({'color': 'rgb(0, 0, 128)', 'width': 1}))
trace12 = go.Scatter(x = [0, 1, 2], y = [1, 1, 1], line = Line({'color': 'rgb(128, 0, 0)', 'width': 1}))
trace21 = go.Scatter(x = [0, 1, 2], y = [0.5, 0.5, 0.5], line = Line({'color': 'rgb(0, 0, 128)', 'width': 1}))
trace22 = go.Scatter(x = [0, 1, 2], y = [1.5, 1.5, 1.5], line = Line({'color': 'rgb(128, 0, 0)', 'width': 1}))

from plotly.subplots import make_subplots
fig = make_subplots(rows=1, cols=2)
data1 = [trace11, trace12]
data2 = [trace21, trace22]
fig.add_traces(data1, rows=1, cols=1)
fig.add_traces(data2, rows=1, cols=2)
fig.show()
Answered By: Guillermo Garcia

While trying to make subplots of histograms, I ran into a similar problem.
My error occurred as I was trying for loops in the wrong way, but the solution below solves the issue you are having. I used add_trace instead of append_trace and used for loop for ease of future use.

from plotly.graph_objs.scatter import Line
from plotly.subplots import make_subplots
import plotly.graph_objs as go

trace11 = go.Scatter(
    x = [0, 1, 2],
    y = [0, 0, 0],
    line = Line({'color': 'rgb(0, 0, 128)', 'width': 1})
)

trace12 = go.Scatter(
    x=[0, 1, 2],
    y=[1, 1, 1],
    line = Line({'color': 'rgb(128, 0, 0)', 'width': 1})
)

trace21 = go.Scatter(
    x = [0, 1, 2],
    y = [0.5, 0.5, 0.5],
    line = Line({'color': 'rgb(0, 0, 128)', 'width': 1})
)

trace22 = go.Scatter(
    x=[0, 1, 2],
    y=[1.5, 1.5, 1.5],
    line = Line({'color': 'rgb(128, 0, 0)', 'width': 1})
)
trace=[trace11, trace12, trace21, trace22]

plot_rows=2
plot_cols=2
fig = make_subplots(rows=plot_rows, cols=plot_cols)

x=0
for i in range(1, plot_rows + 1):
    for j in range(1, plot_cols + 1):
        fig.add_trace(trace[x],
                     row=i,
                     col=j)
        x+=1

fig.update_layout(height=600, width=600)
fig.show()
Answered By: anita.baral

My issue was that I was trying to use a px (plotly express) plot in a trace. The problem, I discovered, is that px returns a complete figure, but add_trace (add_traces, append_trace) wants just the data.

What solved this for me was adding ".data[0]" to the end of my px figure name:

fig = go.Figure()
df = pd.DataFrame({'x':[1,2,3,4], 'y':[5,6,7,8]})
fig2 = px.scatter(df, x="x", y="y")
fig.add_trace(fig2.data[0])
fig.show()

OR you if you use add_traces (plural) you don’t need the [0] qualifier.

fig = go.Figure()
df = pd.DataFrame({'x':[1,2,3,4], 'y':[5,6,7,8]})
fig2 = px.scatter(df, x="x", y="y")
fig.add_traces(fig2.data)
fig.show()

Hope this helps someone save time.

Answered By: I Antonenko
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.