Skip to content

Commit 748db23

Browse files
committed
Merge pull request #417 from plotly/Scatter_Plot_Matrix
Adding Scatterplot Matrix to FigureFactory
2 parents 7a25cee + 78608a7 commit 748db23

File tree

6 files changed

+5269
-1567
lines changed

6 files changed

+5269
-1567
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## [Unreleased]
66

7+
## [1.9.11] - 2016-05-02
8+
### Added
9+
- The FigureFactory can now create scatter plot matrices with `.create_scatterplotmatrix`. Check it out with:
10+
```
11+
import plotly.tools as tls
12+
help(tls.FigureFactory.create_scatterplotmatrix)
13+
```
14+
715
## [1.9.10] - 2016-04-27
816
### Updated
917
- Updated plotly.min.js so the offline mode is using plotly.js v1.10.0

plotly/graph_reference/default-schema.json

Lines changed: 3693 additions & 1565 deletions
Large diffs are not rendered by default.

plotly/tests/test_core/test_tools/test_figure_factory.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1143,4 +1143,3 @@ def test_table_with_index(self):
11431143
# "FigureFactory.create_distplot requires scipy",
11441144
# tls.FigureFactory.create_distplot,
11451145
# hist_data, group_labels)
1146-

plotly/tests/test_optional/test_figure_factory.py

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from nose.tools import raises
99

1010
import numpy as np
11+
import pandas as pd
1112

1213

1314
class TestDistplot(TestCase):
@@ -529,3 +530,308 @@ def test_dendrogram_colorscale(self):
529530
self.assert_dict_equal(dendro['data'][0], expected_dendro['data'][0])
530531
self.assert_dict_equal(dendro['data'][1], expected_dendro['data'][1])
531532
self.assert_dict_equal(dendro['data'][2], expected_dendro['data'][2])
533+
534+
535+
class TestScatterPlotMatrix(NumpyTestUtilsMixin, TestCase):
536+
537+
def test_dataframe_input(self):
538+
539+
# check: dataframe is imported
540+
df = 'foo'
541+
542+
pattern = (
543+
"Dataframe not inputed. Please use a pandas dataframe to produce "
544+
"a scatterplot matrix."
545+
)
546+
547+
self.assertRaisesRegexp(PlotlyError, pattern,
548+
tls.FigureFactory.create_scatterplotmatrix,
549+
df)
550+
551+
def test_one_column_dataframe(self):
552+
553+
# check: dataframe has 1 column or less
554+
df = pd.DataFrame([1, 2, 3])
555+
556+
pattern = (
557+
"Dataframe has only one column. To use the scatterplot matrix, "
558+
"use at least 2 columns."
559+
)
560+
561+
self.assertRaisesRegexp(PlotlyError, pattern,
562+
tls.FigureFactory.create_scatterplotmatrix,
563+
df)
564+
565+
def test_valid_diag_choice(self):
566+
567+
# make sure that the diagonal param is valid
568+
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]])
569+
570+
self.assertRaises(PlotlyError,
571+
tls.FigureFactory.create_scatterplotmatrix,
572+
df, diag='foo')
573+
574+
def test_forbidden_params(self):
575+
576+
# check: the forbidden params of 'marker' in **kwargs
577+
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]])
578+
579+
kwargs = {'marker': {'size': 15}}
580+
581+
pattern = (
582+
"Your kwargs dictionary cannot include the 'size', 'color' or "
583+
"'colorscale' key words inside the marker dict since 'size' is "
584+
"already an argument of the scatterplot matrix function and both "
585+
"'color' and 'colorscale are set internally."
586+
)
587+
588+
self.assertRaisesRegexp(PlotlyError, pattern,
589+
tls.FigureFactory.create_scatterplotmatrix,
590+
df, **kwargs)
591+
592+
def test_valid_index_choice(self):
593+
594+
# check: index is a column name
595+
df = pd.DataFrame([[1, 2], [3, 4]], columns=['apple', 'pear'])
596+
597+
pattern = (
598+
"Make sure you set the index input variable to one of the column "
599+
"names of your dataframe."
600+
)
601+
602+
self.assertRaisesRegexp(PlotlyError, pattern,
603+
tls.FigureFactory.create_scatterplotmatrix,
604+
df, index='grape')
605+
606+
def test_same_data_in_dataframe_columns(self):
607+
608+
# check: either all numbers or strings in each dataframe column
609+
df = pd.DataFrame([['a', 2], [3, 4]])
610+
611+
pattern = (
612+
"Error in dataframe. Make sure all entries of each column are "
613+
"either numbers or strings."
614+
)
615+
616+
self.assertRaisesRegexp(PlotlyError, pattern,
617+
tls.FigureFactory.create_scatterplotmatrix,
618+
df)
619+
620+
df = pd.DataFrame([[1, 2], ['a', 4]])
621+
622+
self.assertRaisesRegexp(PlotlyError, pattern,
623+
tls.FigureFactory.create_scatterplotmatrix,
624+
df)
625+
626+
def test_same_data_in_index(self):
627+
628+
# check: either all numbers or strings in index column
629+
df = pd.DataFrame([['a', 2], [3, 4]], columns=['apple', 'pear'])
630+
631+
pattern = (
632+
"Error in indexing column. Make sure all entries of each column "
633+
"are all numbers or all strings."
634+
)
635+
636+
self.assertRaisesRegexp(PlotlyError, pattern,
637+
tls.FigureFactory.create_scatterplotmatrix,
638+
df, index='apple')
639+
640+
df = pd.DataFrame([[1, 2], ['a', 4]], columns=['apple', 'pear'])
641+
642+
self.assertRaisesRegexp(PlotlyError, pattern,
643+
tls.FigureFactory.create_scatterplotmatrix,
644+
df, index='apple')
645+
646+
def test_valid_palette(self):
647+
648+
# check: the palette argument is in a acceptable form
649+
df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]],
650+
columns=['a', 'b', 'c'])
651+
652+
self.assertRaisesRegexp(PlotlyError, "You must pick a valid "
653+
"plotly colorscale name.",
654+
tls.FigureFactory.create_scatterplotmatrix,
655+
df, use_theme=True, index='a',
656+
palette='fake_scale')
657+
658+
pattern = (
659+
"The items of 'palette' must be tripets of the form a,b,c or "
660+
"'rgbx,y,z' where a,b,c belong to the interval 0,1 and x,y,z "
661+
"belong to 0,255."
662+
)
663+
664+
self.assertRaisesRegexp(PlotlyError, pattern,
665+
tls.FigureFactory.create_scatterplotmatrix,
666+
df, use_theme=True, palette=1, index='c')
667+
668+
def test_valid_endpts(self):
669+
670+
# check: the endpts is a list or a tuple
671+
df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]],
672+
columns=['a', 'b', 'c'])
673+
674+
pattern = (
675+
"The intervals_endpts argument must be a list or tuple of a "
676+
"sequence of increasing numbers."
677+
)
678+
679+
self.assertRaisesRegexp(PlotlyError, pattern,
680+
tls.FigureFactory.create_scatterplotmatrix,
681+
df, use_theme=True, index='a',
682+
palette='Blues', endpts='foo')
683+
684+
# check: the endpts are a list of numbers
685+
self.assertRaisesRegexp(PlotlyError, pattern,
686+
tls.FigureFactory.create_scatterplotmatrix,
687+
df, use_theme=True, index='a',
688+
palette='Blues', endpts=['a'])
689+
690+
# check: endpts is a list of INCREASING numbers
691+
self.assertRaisesRegexp(PlotlyError, pattern,
692+
tls.FigureFactory.create_scatterplotmatrix,
693+
df, use_theme=True, index='a',
694+
palette='Blues', endpts=[2, 1])
695+
696+
def test_scatter_plot_matrix(self):
697+
698+
# check if test scatter plot matrix without index or theme matches
699+
# with the expected output
700+
df = pd.DataFrame([[2, 'Apple'], [6, 'Pear'],
701+
[-15, 'Apple'], [5, 'Pear'],
702+
[-2, 'Apple'], [0, 'Apple']],
703+
columns=['Numbers', 'Fruit'])
704+
705+
test_scatter_plot_matrix = tls.FigureFactory.create_scatterplotmatrix(
706+
df, diag='scatter', height=1000, width=1000, size=13,
707+
title='Scatterplot Matrix', use_theme=False
708+
)
709+
710+
exp_scatter_plot_matrix = {
711+
'data': [{'marker': {'size': 13},
712+
'mode': 'markers',
713+
'showlegend': False,
714+
'type': 'scatter',
715+
'x': [2, 6, -15, 5, -2, 0],
716+
'xaxis': 'x1',
717+
'y': [2, 6, -15, 5, -2, 0],
718+
'yaxis': 'y1'},
719+
{'marker': {'size': 13},
720+
'mode': 'markers',
721+
'showlegend': False,
722+
'type': 'scatter',
723+
'x': ['Apple',
724+
'Pear',
725+
'Apple',
726+
'Pear',
727+
'Apple',
728+
'Apple'],
729+
'xaxis': 'x2',
730+
'y': [2, 6, -15, 5, -2, 0],
731+
'yaxis': 'y2'},
732+
{'marker': {'size': 13},
733+
'mode': 'markers',
734+
'showlegend': False,
735+
'type': 'scatter',
736+
'x': [2, 6, -15, 5, -2, 0],
737+
'xaxis': 'x3',
738+
'y': ['Apple',
739+
'Pear',
740+
'Apple',
741+
'Pear',
742+
'Apple',
743+
'Apple'],
744+
'yaxis': 'y3'},
745+
{'marker': {'size': 13},
746+
'mode': 'markers',
747+
'showlegend': False,
748+
'type': 'scatter',
749+
'x': ['Apple',
750+
'Pear',
751+
'Apple',
752+
'Pear',
753+
'Apple',
754+
'Apple'],
755+
'xaxis': 'x4',
756+
'y': ['Apple', 'Pear', 'Apple', 'Pear', 'Apple', 'Apple'],
757+
'yaxis': 'y4'}],
758+
'layout': {'height': 1000,
759+
'showlegend': True,
760+
'title': 'Scatterplot Matrix',
761+
'width': 1000,
762+
'xaxis1': {'anchor': 'y1',
763+
'domain': [0.0, 0.45]},
764+
'xaxis2': {'anchor': 'y2',
765+
'domain': [0.55, 1.0]},
766+
'xaxis3': {'anchor': 'y3',
767+
'domain': [0.0, 0.45], 'title': 'Numbers'},
768+
'xaxis4': {'anchor': 'y4',
769+
'domain': [0.55, 1.0], 'title': 'Fruit'},
770+
'yaxis1': {'anchor': 'x1',
771+
'domain': [0.575, 1.0], 'title': 'Numbers'},
772+
'yaxis2': {'anchor': 'x2',
773+
'domain': [0.575, 1.0]},
774+
'yaxis3': {'anchor': 'x3',
775+
'domain': [0.0, 0.425], 'title': 'Fruit'},
776+
'yaxis4': {'anchor': 'x4',
777+
'domain': [0.0, 0.425]}}
778+
}
779+
780+
self.assert_dict_equal(test_scatter_plot_matrix['data'][0],
781+
exp_scatter_plot_matrix['data'][0])
782+
783+
self.assert_dict_equal(test_scatter_plot_matrix['data'][1],
784+
exp_scatter_plot_matrix['data'][1])
785+
786+
self.assert_dict_equal(test_scatter_plot_matrix['layout'],
787+
exp_scatter_plot_matrix['layout'])
788+
789+
def test_scatter_plot_matrix_kwargs(self):
790+
791+
# check if test scatter plot matrix matches with
792+
# the expected output
793+
df = pd.DataFrame([[2, 'Apple'], [6, 'Pear'],
794+
[-15, 'Apple'], [5, 'Pear'],
795+
[-2, 'Apple'], [0, 'Apple']],
796+
columns=['Numbers', 'Fruit'])
797+
798+
test_scatter_plot_matrix = tls.FigureFactory.create_scatterplotmatrix(
799+
df, index='Fruit', endpts=[-10, -1], diag='histogram',
800+
height=1000, width=1000, size=13, title='Scatterplot Matrix',
801+
use_theme=True, palette='YlOrRd', marker=dict(symbol=136)
802+
)
803+
804+
exp_scatter_plot_matrix = {
805+
'data': [{'marker': {'color': 'rgb(128.0, 0.0, 38.0)'},
806+
'showlegend': False,
807+
'type': 'histogram',
808+
'x': [2, -15, -2, 0],
809+
'xaxis': 'x1',
810+
'yaxis': 'y1'},
811+
{'marker': {'color': 'rgb(255.0, 255.0, 204.0)'},
812+
'showlegend': False,
813+
'type': 'histogram',
814+
'x': [6, 5],
815+
'xaxis': 'x1',
816+
'yaxis': 'y1'}],
817+
'layout': {'barmode': 'stack',
818+
'height': 1000,
819+
'showlegend': True,
820+
'title': 'Scatterplot Matrix',
821+
'width': 1000,
822+
'xaxis1': {'anchor': 'y1',
823+
'domain': [0.0, 1.0],
824+
'title': 'Numbers'},
825+
'yaxis1': {'anchor': 'x1',
826+
'domain': [0.0, 1.0],
827+
'title': 'Numbers'}}
828+
}
829+
830+
self.assert_dict_equal(test_scatter_plot_matrix['data'][0],
831+
exp_scatter_plot_matrix['data'][0])
832+
833+
self.assert_dict_equal(test_scatter_plot_matrix['data'][1],
834+
exp_scatter_plot_matrix['data'][1])
835+
836+
self.assert_dict_equal(test_scatter_plot_matrix['layout'],
837+
exp_scatter_plot_matrix['layout'])

0 commit comments

Comments
 (0)