Skip to content

Sparklines Figure Factory #888

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

Closed
wants to merge 23 commits into from
Closed

Sparklines Figure Factory #888

wants to merge 23 commits into from

Conversation

Kully
Copy link
Contributor

@Kully Kully commented Nov 29, 2017

@jackparmer progress so far

screen shot 2017-11-29 at 3 28 32 pm

you can set column_widths (like in go.Table) with a list [1, 4, 2, ...]
you set the chart types with a list: i.e. the one above is produced with chart_types=['name', 'bullet', 'line', 'avg', 'bar']

# TODO:
# add  more color variety
# add tests

any suggestions?

@Kully
Copy link
Contributor Author

Kully commented Nov 29, 2017

Playing around with the column_width param:

fig = ff.create_sparkline(
    df, chart_types=['name', 'bullet', 'bar'],
    column_width=[1, 7, 10], left_aligned=False
)
py.iplot(fig, filename='my-sparkline-obvious-column-widths')

https://plot.ly/~AdamKulidjian/5610

Picture:
screen shot 2017-11-29 at 3 35 04 pm

@jackparmer
Copy link
Contributor

Looks like they're on the right track! You happy with them?

Can you do a lines example? For example, can you recreate this?
image

I think there's more vertical and horizontal padding needed between the subplots:

image

Can you also try adding an option to alternate row color? As a sort of benchmark, see how close you can get to this:

image

(From Stephen's blog)

@Kully
Copy link
Contributor Author

Kully commented Dec 8, 2017

Some of the possibilities:
screen shot 2017-12-08 at 3 30 58 pm

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/Canada%20Immigration.csv')

fig = ff.create_sparkline(
    df, chart_types=['name', 'line', 'bullet', 'bar'],
    textalign='center', show_titles=True,
    horizontal_spacing=0, alternate_row_color=True,
    lane_colors=('rgba(251, 252, 230, 0.6)',
                 'rgba(255, 245, 219, 0.6)'),
    title=''
)
py.iplot(fig)

|
V

screen shot 2017-12-08 at 3 55 48 pm

@Kully
Copy link
Contributor Author

Kully commented Dec 11, 2017

@chriddyp and @cldougl ready for a review when tests pass 😛

@chriddyp
Copy link
Member

@Kully - do you have a sample notebook or documentation that shows how this works?

@jackparmer
Copy link
Contributor

jackparmer commented Dec 11, 2017 via email

@Kully
Copy link
Contributor Author

Kully commented Dec 11, 2017

@Kully - do you have a sample notebook or documentation that shows how this works?

I'll make one now. Caught another bug in the FF so I'll deal with that first

@Kully
Copy link
Contributor Author

Kully commented Dec 12, 2017

@jackparmer @chriddyp
here's a notebook with nearly all the features of the ff: https://plot.ly/~AdamKulidjian/6128

@jackparmer
Copy link
Contributor

jackparmer commented Dec 12, 2017

This looks really nice. Nice work. A few small suggestions and usage questions that jumped out at me:

  • Maybe label instead of name
  • text_align instead of textalign to match the other kwargs
  • Maybe row instead of lane and row_colors instead of lane_colors?
  • What is colors? Maybe rename this sparkline_colors or trace_colors?
  • Is column_width using a grid system (eg column_width=[1, 13] and column_width=[1, 4, 4])? I can't figure it out. Should it be absolute pixels instead?
  • The mpg.csv example is great!

@jackparmer
Copy link
Contributor

It would nice if colors supported varying trace colors by row (such as in the plot below). I'm also thinking layouts like all of the row traces are grey except the 49th one, which is red.

image

@Kully
Copy link
Contributor Author

Kully commented Dec 12, 2017

Is column_width using a grid system (eg column_width=[1, 13] and column_width=[1, 4, 4])? I can't figure it out. Should it be absolute pixels instead?

column_width comes from the go.Table param of the same name (actually columnwidth) and which is now a new param in tls.make_subplots. It's a ratio assigned for each column. So [1, 2] for a 2-column subplot means column 1 gets 1/3 of the width and column 2 gets 2/3 of the total width.

@Kully
Copy link
Contributor Author

Kully commented Dec 13, 2017

It would nice if colors supported varying trace colors by row (such as in the plot below). I'm also thinking layouts like all of the row traces are grey except the 49th one, which is red.

We could do something simple like alternating through the Plotly colors if the user wants changing trace colors. But we'll run out quickly for large enough figures.

How do you feel about
a) interpolating between existing plotly colors when we go through all 10
b) being able to enter a Plotly Colorscale name and the traces getting their own equally spaced color within the colorspectrum of that colorscale

I have all this machinery to do this stuff easily 🎰

  • being able to assign all N colors for N rows

@jackparmer
Copy link
Contributor

jackparmer commented Dec 13, 2017

You already have colors which seems to take a list of 2 colors (Is that correct, these 2 colors are primary and secondary trace colors for each row?). What if colors could also take a list of list of colors. For example:

What you have now:

colors = ['#e763fa', '#ab63fa']

Same as what you have now, but alternates primary and secondary trace colors by row:

colors =[['#e763fa', '#ab63fa'], ['#636efa', '#EF553B']]

Traces of every 3rd row are red (other traces are grey):

colors =[['#444', '#ccc'], ['#444', '#ccc'], ['#ff0000', '#ff0000',]]

1D lists longer than 2 elements are the primary trace color for each row, so this could be a colorscale

colors=['#00cc96', '#00cc96', '#00cc96']
Could set the secondary color as 0.5 x opacity of the primary color, like area chart fills?

interpolating between existing plotly colors when we go through all 10

I think if given an array, we should cycle instead of interpolate. This is what table does and I don't see much use for sequential or diverging color scale rows.

Maybe try this idea out and see if you can replicate something like:

image

@Kully
Copy link
Contributor Author

Kully commented Dec 14, 2017

Maybe try this idea out and see if you can replicate something like:

I like this whole idea. It covers all the bases, including first 48 rows grey and last one red

@Kully
Copy link
Contributor Author

Kully commented Dec 14, 2017

1D lists longer than 2 elements are the primary trace color for each row, so this could be a colorscale

My thoughts on this now are that users will more often than not, not want to specify the second color and will be okay with a light color as half the opacity of the main. Why don't we:

  • allow users to input lists like:
trace_colors =[['#e763fa', '#ab63fa'], 'rgb(240, 10, 14)', ['#636efa', '#EF553B'], '#636efa']

and we

  • interpret each nested single color as the primary color of that row

and

  • treat the nested lists as the obvious darklight color combo

@Kully
Copy link
Contributor Author

Kully commented Dec 14, 2017

@jackparmer new notebook of charts/features: https://plot.ly/~AdamKulidjian/6215

@Kully
Copy link
Contributor Author

Kully commented Dec 14, 2017

@chriddyp ready for a review (when tests pass)

Applied to all rows
:param (float) alternate_row_color: set to True to enable the alternate
row coloring of the chart. Uses the colors from param 'lane_colors'
:param (list) lane_colors: a list/tuple of two colors that are used to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be helpful to add the default colors here

Applied to all columns
:param (float) vertical_spacing: Space between subplot rows.
Applied to all rows
:param (float) alternate_row_color: set to True to enable the alternate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a float or a bool? can the default (True) be included here too?

Applied to all rows
:param (float) alternate_row_color: set to True to enable the alternate
row coloring of the chart. Uses the trace_colors from param 'row_colors'
:param (list) row_colors: a list/tuple of colors that are used to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe include the default here too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll include more of the defaults

@Kully
Copy link
Contributor Author

Kully commented Jan 15, 2018

@chriddyp so I like most of your suggestions, but I found something that may pose a problem.

The entire code in facet_grid is partitioned in terms of what kind of color you are using: colorscale name (ex Viridis), or the column name for color. I was using a new syntax for color in the _sparkline FF I was working on, something like:

colors =[['#444', '#ccc'], ['#444', '#ccc'], ['#ff0000', '#ff0000',]]

I really want to keep this method for coloring (first column gets first list: [lightcolor, darkcolor]) What do you think?

@Kully
Copy link
Contributor Author

Kully commented Jan 15, 2018

There's also the issue of the other way in which a user can use sparklines, which is just giving the API a dataframe, and then just mapping each column to a row and entering charts based on a chart_types variable. The current structure of facet grids doesn't allow this to be naturally added in, and it's gonna take a lot of extra rewritting to make that work.

For these two reasons, I think it would make more sense to keep sparklines as its own FigureFactory, but perhaps to also change the variable names in sparklines to match those in facet_grid.

But you do make good points about the familiarity of the already existing FF and building on top of it.

Any thoughts?

@Kully
Copy link
Contributor Author

Kully commented Apr 9, 2018

Goals:

  • replicate accurately this notebook: https://plot.ly/~AdamKulidjian/6128/_1-simple-example/
  • replace _annotation_dict() in _facet_grid.py with annotation_dict_for_label in ff.utils.py
  • theme='sparklines' that accurately replicate the old sparklines
  • all the old trace types from sparklines ['line', 'bullet', 'label', 'avg', 'area']
  • add ability to use non-tidy data in facet_grid
  • add column_width to facet_grid
    • _facet_grid
    • _facet_grid_color_numerical
    • _facet_grid_color_categorical
  • make subplots not use shared axes
  • add bullet_variable param to indicate selected variable (x or y) if both x and y are in the trace data
  • make trace_types take lists: eg. trace_type = ['scatter', 'bullet', 'avg']
  • add data ordering for facet_grid/sparklines (for dash facet_grid ex. @alishobeiri )
  • allow trace_dimension to be a list eg. ['x', 'x+y', 'y']with length == num_of_cols

Documentation:

  • update the doc page with examples of Sparklines OR make a new doc page
    • explain how bullet chart is constructed
  • doc string -> sparklines examples

Issues:

  • trace_colors=[[color1a, color1b], color2]] fails. All single colors or all 2-list colors works

@Kully
Copy link
Contributor Author

Kully commented Apr 23, 2018

For the Bullet Charts in this FF:

I am redefining the various elements in the ones that are displayed in sparklines. Since we are using 1D data, there is only so much we can do.

Bullet charts were made for the purpose of comparing a performance (thin dark line) to a target (the vertical bar marker) with gradated qualitative sections representing BAD, OK, GOOD, etc.

image

I think we could pull off something with 1D data that is interesting. How about the max value is the vertical marker, the thin black bar is the mean and we only have one thick bar which is the standard dev?

WDYT?
cc. @jackparmer @chriddyp

@jackparmer
Copy link
Contributor

How about the max value is the vertical marker, the thin black bar is the mean and we only have one thick bar which is the standard dev?

Hm... toughy. What about leaving it to the user to define what these things mean? They'll have to calculate mean, max, etc on their own, but this would provide the most flexibility and forward compatibility.

@Kully
Copy link
Contributor Author

Kully commented Apr 23, 2018

Hm... toughy. What about leaving it to the user to define what these things mean?

While it's more robust, I don't like what this will mean for users who just want a quick and dirty bullet chart. What would the syntax for that look like?

@jackparmer
Copy link
Contributor

Yeah, I can see that. Let's go with your proposal - I think it's totally reasonable. 👍

@jonmmease
Copy link
Contributor

Hi @Kully , I haven't read through this PR thread yet, but is this something you're planning to keep working on?

@Kully
Copy link
Contributor Author

Kully commented Sep 28, 2018

but is this something you're planning to keep working on?

Yes

@jonmmease jonmmease removed the question label Oct 2, 2018
@JeroneGagliano
Copy link

Do you have a timeline on when this PR will be merged with the master branch?
Thanks!

@JeroneGagliano
Copy link

Hi @Kully , I haven't read through this PR thread yet, but is this something you're planning to keep working on?

Hi @jonmmease
Adam Kulidjian says he is no longer working on this Sparklines addition to the Figure Factory. Is someone else picking this up?
Thanks
Jerone

@JeroneGagliano
Copy link

@chriddyp and @jonmmease
I have pulled Kully's latest commit 8d665ac imported it and had success running his the first few examples after fixing a couple of errors in the sparklines.py file. As an engineer, and not a real programmer, I am not comfortable finishing sparklines-ff to merge into master. I would be happy to participate in testing and passing along the code errors I found.

@nicolaskruchten
Copy link
Contributor

I think this kind of thing is easier to make now with make_subplots and indicator and px and Dash, so I'm going to close out this PR for now.

@nicolaskruchten nicolaskruchten deleted the sparklines-ff branch June 19, 2020 16:10
@firmai
Copy link

firmai commented Jun 21, 2021

Hi @nicolaskruchten , In finance (currently) at least, you can't build a state of the art dashboard without sparklines see e.g, yahoo. https://finance.yahoo.com/world-indices/

At which point would we be able to build something similar using make_subplots and indicator and px and Dash? Is this currently a wip?

@nicolaskruchten
Copy link
Contributor

These kinds of tables are quite common, but IMO a data visualization library such as plotly is a poor fit for generating the whole thing. Dash is what I would recommend for doing this kind of thing in Python, specifically the Dash DataTable. Sparklines are currently supported there via this approach: https://community.plotly.com/t/sparklines-as-fonts-embedding-minimal-sparklines-in-tables-components/39468

@firmai
Copy link

firmai commented Jul 7, 2021

Thanks, I tried dash, it unfortunately doesn't work, I get about 20% there after 3 days spent. Hopefully at some point a company could sponsor this so that it can be open sourced. @Kully was approaching something interesting, a templatable framework that could be used by ordinary users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants