Skip to content

support arrays of color and colorscale for line and fillcolor of plotly.graph_objects.Scatter #5259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jleaves opened this issue Nov 10, 2020 · 5 comments
Labels
feature something new P3 backlog

Comments

@jleaves
Copy link

jleaves commented Nov 10, 2020

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 and plotly.graph_objects.Scatter.marker.line supports assigning colors by arrays of color along with colorscale.

Could the same color-setting techniques be allowed for plotly.graph_objects.Scatter.line and plotly.graph_objects.Scatter.fillcolor as well?

p.s. Links to the current documentation:

  1. The following supports arrays of color with colorscale:
  1. The following doesn't support arrays of color with colorscale:
@nicolaskruchten
Copy link
Contributor

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 :)

@alexcjohnson
Copy link
Collaborator

I'm guessing the variable fillcolor would be like https://stackoverflow.com/a/59950664/9188800
Q6kC7gQ

The line case is covered in #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.

@jleaves
Copy link
Author

jleaves commented Nov 22, 2020

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:

newplot

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?

@ryani
Copy link

ryani commented Dec 21, 2020

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.

@yotkadata
Copy link

yotkadata commented Aug 15, 2023

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

key-west-united-states-temperature-mean-2023-ref-1961-1990-interactive

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

key-west-united-states-temperature-mean-2023-ref-1961-1990-interactive

In the end this works, but it's quite slower performance-wise and also feels more "hacky".

@gvwilson gvwilson self-assigned this Jul 5, 2024
@gvwilson gvwilson removed their assignment Aug 2, 2024
@gvwilson gvwilson changed the title [Feature Request] Support arrays of color and colorscale for line and fillcolor of plotly.graph_objects.Scatter support arrays of color and colorscale for line and fillcolor of plotly.graph_objects.Scatter Aug 9, 2024
@gvwilson gvwilson added feature something new P3 backlog labels Aug 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new P3 backlog
Projects
None yet
Development

No branches or pull requests

6 participants