Open jleaves opened 3 years ago
These are both good ideas although a bit trickier to implement because these arrays wouldn't have the same lengths as the others in the trace: the line.color would be 1 element shorter, and the fillcolor one would be different again. I'm actually not clear what kind of plot you'd like to make with variable fillcolor :)
I'm guessing the variable fillcolor would be like https://stackoverflow.com/a/59950664/9188800
The line case is covered in https://github.com/plotly/plotly.js/issues/581 - short answer: big pain in SVG, more manageable in scattergl
. I'd say the same goes for variable fillcolor
@nicolaskruchten I guess it could either be 1 element shorter or the same length, depending on exactly what you want the color to mean, and whether you want a smooth variation or a single color per segment. There may be use cases for both, and neither is particularly easy in SVG.
These are both good ideas although a bit trickier to implement because these arrays wouldn't have the same lengths as the others in the trace: the line.color would be 1 element shorter, and the fillcolor one would be different again. I'm actually not clear what kind of plot you'd like to make with variable fillcolor :)
Sorry for the late reply.
I was trying to plot shapes with different colors. Each polygon (plotly.graph_objects.Scatter.fillcolor
) comes with a numeric property which I want to illustrate by the "fill" color. Furthermore, the common boundary of two polygons (plotly.graph_objects.Scatter.line
) also has a numeric property which I want to illustrate (now maybe by "width", but support for "color" may be helpful as well).
The simplist graph would look like this:
Currently, I have to write my own "color mapping" function, something like the function map_z2color
in this section. With regards to my specific application, I successfully work around this issue with the above method.
But still, I guess my naive method may have performance issues as I have to manually produce a string of color for every polygon and every boundary. So maybe the "feature request" is still a good improvement? Any suggestions?
I'm also interested in this feature. I'd like the lines to change color via something like the heatmap z component. I'd actually prefer gradient lines (blending between the values at each point) but using the z value of the start or end point would be fine.
My use case is scatter lines representing 2d data over time, and I want the trail to fade out as the points get further in the past.
It would be really great to be able to use arrays/lists of colors for line and fillcolor. I am currently working on an interactive version of my MeteoHist App and I could've really used this feature. Instead, I ended up adding 365 traces to my Plot - one for every day of the year. This might serve as a workaround for others:
With a bar chart, I could get more or less what I want in one trace (code from inside a class):
# Define opacity depending on whether peak alpha is enabled
opacity = (
self.df_t[f"{self.year}_alpha"]
if self.settings["peak_alpha"]
else np.ones(len(self.df_t))
)
# Get colorscale from method
# Results in an array of colors the same length as self.df_t
colors = self.get_colorscale()
# Display a simpler and faster plot if chart_type is "bar"
if chart_type == "bar":
fig.add_trace(
go.Bar(
x=self.df_t["date"],
y=self.df_t[f"{self.year}_diff"],
base=self.df_t["mean"],
marker=dict(
color=colors,
line_width=0,
opacity=opacity,
),
)
)
return fig
But I like much better to draw an area between the mean and the current value. Since I can't use the color array directly, I have to create many "shapes" (actually they are Scatter traces):
# For each day, add a filled area between the mean and the year's value
for i in range(len(self.df_t) - 1):
# Define x and y values to draw a polygon between mean and values of today and tomorrow
date_today = self.df_t["date"].iloc[i]
date_tomorrow = self.df_t["date"].iloc[i + 1]
mean_today = self.df_t["mean"].iloc[i]
mean_tomorrow = self.df_t["mean"].iloc[i + 1]
value_today = self.df_t[f"{self.year}"].iloc[i]
value_tomorrow = self.df_t[f"{self.year}"].iloc[i + 1]
# If one day is above and the other below the mean, set the value to the mean
if (value_today > mean_today) ^ (value_tomorrow > mean_tomorrow):
value_tomorrow = mean_tomorrow
fig.add_trace(
go.Scatter(
name=f"Daily value {self.df_t['date'].iloc[i].strftime('%d.%m.%Y')}",
x=[date_today, date_today, date_tomorrow, date_tomorrow],
y=[mean_today, value_today, value_tomorrow, mean_tomorrow],
line_width=0,
fill="toself",
fillcolor=colors[i],
showlegend=False,
mode="lines",
opacity=opacity[i],
hoverinfo="skip",
)
)
return fig
In the end this works, but it's quite slower performance-wise and also feels more "hacky".
Coming from plotly.py. Since this is about the
plotly.graph_objects
module, the issue is posted here.Currently, only
plotly.graph_objects.Scatter.marker
,plotly.graph_objects.Scatter.marker.gradient
andplotly.graph_objects.Scatter.marker.line
supports assigning colors by arrays ofcolor
along withcolorscale
.Could the same color-setting techniques be allowed for
plotly.graph_objects.Scatter.line
andplotly.graph_objects.Scatter.fillcolor
as well?p.s. Links to the current documentation:
colorscale
:colorscale
: