-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Facet grid FigureFactory #731
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
Conversation
plotly/figure_factory/_facet_grid.py
Outdated
num_of_rows = len(data[facet_row].unique()) | ||
|
||
if facet_col: | ||
num_of_cols = len(data[facet_col].unique()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts about adding binning for numerical columns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't thinking about it but I can after I get something working. I'm not finished with the code here, so I can ping you when I do
plotly/figure_factory/__init__.py
Outdated
@@ -16,3 +16,4 @@ | |||
from plotly.figure_factory._table import create_table | |||
from plotly.figure_factory._trisurf import create_trisurf | |||
from plotly.figure_factory._violin import create_violin | |||
from plotly.figure_factory._facet_grid import create_facet_grid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imports in alphabetical order
How 1-1 is this figure factory with the ggplot2 facet geom? Would be great to see some screenshot output examples when this gets closer. |
pretty close, just missing some variables right now. Yeah, I'm gonna put together either screenshots or a notebook presentation or both. |
@jackparmer Here's my progress so far. Things that we could add:
Feel free to make suggestions. π |
@Kully This looks very cool! Can you please make a Jupyter notebook that uses these dataframes and recreates these examples using your FigureFactory? http://ggplot2.tidyverse.org/reference/facet_grid.html I think this will be a nice way to be sure we're covering canonical faceting usage. |
For sure! |
@@ -3,6 +3,7 @@ | |||
from plotly.exceptions import PlotlyError | |||
|
|||
import plotly.tools as tls | |||
import plotly.figure_factory as ff |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for updating all of these @Kully !
**kwargs) | ||
|
||
def test_unequal_data_label_length(self): | ||
kwargs = {'hist_data': [[1, 2]], 'group_labels': ['group', 'group2']} | ||
self.assertRaises(PlotlyError, tls.FigureFactory.create_distplot, | ||
self.assertRaises(PlotlyError, ff.create_distplot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same- one line?
@@ -32,24 +33,24 @@ def test_wrong_histdata_format(self): | |||
# will fail) | |||
|
|||
kwargs = {'hist_data': [1, 2, 3], 'group_labels': ['group']} | |||
self.assertRaises(PlotlyError, tls.FigureFactory.create_distplot, | |||
self.assertRaises(PlotlyError, ff.create_distplot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this could be one line now (with **kwargs)
**kwargs) | ||
|
||
kwargs = {'hist_data': [[1, 2], [1, 2, 3]], 'group_labels': ['group']} | ||
self.assertRaises(PlotlyError, tls.FigureFactory.create_distplot, | ||
self.assertRaises(PlotlyError, ff.create_distplot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same - one line?
**kwargs) | ||
|
||
def test_simple_distplot_prob_density(self): | ||
|
||
# we should be able to create a single distplot with a simple dataset | ||
# and default kwargs | ||
|
||
dp = tls.FigureFactory.create_distplot(hist_data=[[1, 2, 2, 3]], | ||
dp = ff.create_distplot(hist_data=[[1, 2, 2, 3]], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix spacing w/ lines below
plotly/figure_factory/_facet_grid.py
Outdated
from plotly.figure_factory import utils | ||
import plotly.colors as colors | ||
|
||
from plotly.graph_objs import graph_objs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can group all from plotly...
imports together
plotly/figure_factory/_facet_grid.py
Outdated
) | ||
|
||
return annotation_dict | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can add 2 new lines between def
s
fig['layout']['annotations'] = annotations | ||
|
||
return fig | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 spaces between defs
plotly/figure_factory/_facet_grid.py
Outdated
colorscale=None, color_dict=None, title='facet grid', | ||
height=600, width=600, **kwargs): | ||
""" | ||
Returns data for a facet grid. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this returns a figure right? not just the data object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed 'data' -> 'figure'
plotly/figure_factory/_facet_grid.py
Outdated
""" | ||
if not pd: | ||
raise exceptions.ImportError( | ||
"'pandas' must be imported for this FigureFactory." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we changed the syntax I would probably say figure_factory or figure type or chart type
@Kully looks like a weird thing is going on when toggling the traces: |
Yeah, it's pretty wack. For some reason when a subplot is empty, the background just disappears. I think it has to do with all the customization I'm using. Are you a fan of having all those duplicate trace icons, or is one per category enough. |
plotly/figure_factory/_facet_grid.py
Outdated
colormap will be treated as categorical (True) or sequential (False). | ||
Default = False. | ||
:param (bool) widen_frame: if set to True, all points in each subplot | ||
are strickly contained in the region of the subplot by increasing the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spelling: strictly
plotly/figure_factory/_facet_grid.py
Outdated
:param (bool) widen_frame: if set to True, all points in each subplot | ||
are strickly contained in the region of the subplot by increasing the | ||
maximum and minimum range values by 1. Setting to False doesn't do | ||
anything. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe "If False
, then points may be plotted on the edge of the frame."
plotly/figure_factory/_facet_grid.py
Outdated
anything. | ||
Default = False | ||
:param (str|dict) facet_row_labels: set to either 'name' or a dictionary | ||
of all the values in the facetting row mapped to some text to show up |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spelling: faceting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and it's all of the "unique values" not just "values", right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct
plotly/figure_factory/_facet_grid.py
Outdated
Default = False | ||
:param (str|dict) facet_row_labels: set to either 'name' or a dictionary | ||
of all the values in the facetting row mapped to some text to show up | ||
in the label annotations. If None, labelling works like usual. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spelling: labeling
plotly/figure_factory/_facet_grid.py
Outdated
:param (int) width: the width of the facet grid figure. | ||
:param (int) size: point size in pixels. | ||
:param (str) trace_type: decides the type of plot to appear in the | ||
facet grid. The options are 'scatter' and 'scattergl'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
although presumably you could pass in something like histogram
and a set of kwargs
to customize that histogram right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could even skip applying the marker
and mode
options if type is not in ['scatter', 'scattergl']
, allowing users to create valid facet_grids with heatmaps, histograms, 2dhistograms, etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order for histogram to work, you'd need to also make x
and y
optional too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this pass, can we not include trace types besides scatter
and scattergl
? mode
for example is not a valid key for a bar chart, and would result in an error.
I don't think turning off validation for the figure is a good idea, but the way I'd implement the option to add other trace types is to have a dictionary of keys that would go in the trace dict
for each specific trace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking pretty good so far! This is going to be really great, I can already see how I'll use this in Dash :) My main comments around around:
- Numerical binning instead of using the unique numerical values
- Making the code DRYer
I'll finish up reviewing this evening!
Some other thoughts as I play around with this:
|
Is there a requirement that the graphs need to look like
Some people like the theme however, and so we can keep it in with maybe a Here is a little redesign: Here is the code I'm using to convert the
|
plotly/figure_factory/_facet_grid.py
Outdated
kwargs.pop('marker', None) | ||
|
||
# make sure dataframe index starts at 0 | ||
df.index = range(len(df)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Damn, you're right. I can fix that with some rewriting.
plotly/figure_factory/_facet_grid.py
Outdated
if key not in facet_row_labels.keys(): | ||
unique_keys = df[facet_row].unique().tolist() | ||
raise exceptions.PlotlyError( | ||
"If you are using a dictioanry for custom labels for " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spelling: "dictionary"
plotly/figure_factory/_facet_grid.py
Outdated
if key not in facet_col_labels.keys(): | ||
unique_keys = df[facet_col].unique().tolist() | ||
raise exceptions.PlotlyError( | ||
"If you are using a dictioanry for custom labels for " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spelling: "dictionary".
plotly/figure_factory/_facet_grid.py
Outdated
max_range = math.ceil(max_range) | ||
if widen_frame: | ||
min_range -= 1 | ||
max_range += 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call in fixing the range across all subplots so that it's easy to compare values.
I think we can be a bit smarter about setting the autorange though and then make it the default and remove this widen_frame
argument:
- Adding/subtracting
1
like this won't work if the numerical ranges are really big or if the numerical ranges are within a small range like between0.5
and0.6
(in which case it'll end up making the range too large) - Instead, why don't we just make it say 5% bigger than the absolute range. I believe this is how plotly.js does it. Something like:
range = [min - (max - min) * 0.05, max + (max - min) * 0.05]
. You could ask the #plotly_js folks exactly what value they use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea Chris
'Blackbody': ['rgb(0,0,0)', 'rgb(160,200,255)'], | ||
'Earth': ['rgb(0,0,130)', 'rgb(255,255,255)'], | ||
'Electric': ['rgb(0,0,0)', 'rgb(255,250,220)'], | ||
'Viridis': ['#440154', '#fde725'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These colorscales seem a little off - aren't there supposed to be more than 2 colors in them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that colorscale list is not correct. It's being used by _scatterplot.py
for colorscales, so I eventually want to make a PR to replace the colorscales in utils with plotly.colors.PLOTLY_SCALES
(the proper one) and rewrite the way scatterplot handles colorscales.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will handle in a separate PR with a new issue: #769
Good read. It's funny because the "black" that they pit against the examples of nearly-black in app layouts are actually not |
@jackparmer @chriddyp @cldougl
Sounds good? |
SGTM! |
β¦ facet_grid Going to merge because I feel like it
@jackparmer @chriddyp π ? |
Yeah, that sounds good. In the meantime, we can document a workflow where the user creates their own bins in their dataframe and facets off of that. For example:
or, with custom labels:
|
thanks for making all of those changes. this feature is really great now. π ! |
will be making a notebook for a proper showcase of these charts