@@ -49,6 +49,12 @@ def warning_on_one_line(message, category, filename, lineno,
49
49
except ImportError :
50
50
_numpy_imported = False
51
51
52
+ try :
53
+ import pandas as pd
54
+ _pandas_imported = True
55
+ except ImportError :
56
+ _pandas_imported = False
57
+
52
58
try :
53
59
import scipy as scp
54
60
_scipy_imported = True
@@ -1428,10 +1434,12 @@ class FigureFactory(object):
1428
1434
without notice.
1429
1435
1430
1436
Supported chart types include candlestick, open high low close, quiver,
1431
- and streamline. See FigureFactory.create_candlestick,
1432
- FigureFactory.create_ohlc, FigureFactory.create_quiver, or
1433
- FigureFactory.create_streamline for for more infomation and examples of a
1434
- specific chart type.
1437
+ streamline, distplot, dendrogram, annotated heatmap, and tables. See
1438
+ FigureFactory.create_candlestick, FigureFactory.create_ohlc,
1439
+ FigureFactory.create_quiver, FigureFactory.create_streamline,
1440
+ FigureFactory.create_distplot, FigureFactory.create_dendrogram,
1441
+ FigureFactory.create_annotated_heatmap, or FigureFactory.create_table for
1442
+ more infomation and examples of a specific chart type.
1435
1443
"""
1436
1444
1437
1445
@staticmethod
@@ -1585,6 +1593,13 @@ def _flatten(array):
1585
1593
"flattened! Make sure your data is "
1586
1594
"entered as lists or ndarrays!" )
1587
1595
1596
+ @staticmethod
1597
+ def _hex_to_rgb (value ):
1598
+ value = value .lstrip ('#' )
1599
+ lv = len (value )
1600
+ return tuple (int (value [i :i + lv // 3 ], 16 )
1601
+ for i in range (0 , lv , lv // 3 ))
1602
+
1588
1603
@staticmethod
1589
1604
def create_quiver (x , y , u , v , scale = .1 , arrow_scale = .3 ,
1590
1605
angle = math .pi / 9 , ** kwargs ):
@@ -2509,6 +2524,107 @@ def create_dendrogram(X, orientation="bottom", labels=None,
2509
2524
return {'layout' : dendrogram .layout ,
2510
2525
'data' : dendrogram .data }
2511
2526
2527
+ @staticmethod
2528
+ def create_annotated_heatmap (z , x = None , y = None , text = None ,
2529
+ fontcolor = None , showscale = False ,
2530
+ ** kwargs ):
2531
+ """
2532
+ BETA function that creates annotated heatmaps
2533
+
2534
+ The distplot can be composed of all or any combination of the following
2535
+ 3 components: (1) histogram, (2) curve: (a) kernal density estimation
2536
+ or (b) normal curve, and (3) rug plot. Additionally, multiple distplots
2537
+ (from multiple datasets) can be created in the same plot.
2538
+
2539
+ :param (list[list]) z: z matrix to create heatmap.
2540
+ :param (list) x: x labels. Default = None
2541
+ :param (list) y: y labels. Default = None
2542
+ :param (list[list]) text: Text for annotations. Should be the same
2543
+ dimmensions as the z matrix. If no text is added, the the values of
2544
+ the z matrix are annotated. Default = None
2545
+ :param (list) font_color: Add histogram to distplot? Default = True
2546
+ :param (bool) showscale: Display colorscale. Default = False
2547
+ :param kwargs: kwargs passed through plotly.graph_objs.Heatmap.
2548
+ These kwargs describe other attributes about the annotated Heatmap
2549
+ trace such as the colorscale. For more information on valid kwargs
2550
+ call help(plotly.graph_objs.Heatmap)
2551
+
2552
+ Example 1: Simple distplot of 1 data set
2553
+ ```
2554
+ import plotly.plotly as py
2555
+ from plotly.tools import FigureFactory as FF
2556
+ ```
2557
+ """
2558
+ # TODO: protected until #282
2559
+ from plotly .graph_objs import graph_objs
2560
+ # FigureFactory._validate_annotated_heatmap()
2561
+ annotations = _AnnotatedHeatmap (z , x , y , text , fontcolor ,
2562
+ ** kwargs ).make_annotations ()
2563
+
2564
+ if x and y :
2565
+ trace = dict (type = 'heatmap' ,
2566
+ z = z ,
2567
+ x = x ,
2568
+ y = y ,
2569
+ showscale = showscale ,
2570
+ ** kwargs )
2571
+ else :
2572
+ trace = dict (type = 'heatmap' ,
2573
+ z = z ,
2574
+ showscale = showscale ,
2575
+ ** kwargs )
2576
+
2577
+ data = [trace ]
2578
+ layout = dict (annotations = annotations ,
2579
+ xaxis = dict (ticks = '' , side = 'top' ,
2580
+ gridcolor = 'rgb(0, 0, 0)' ),
2581
+ yaxis = dict (ticks = '' , ticksuffix = ' ' ))
2582
+ return graph_objs .Figure (data = data , layout = layout )
2583
+
2584
+ @staticmethod
2585
+ def create_table (z , index = False ,
2586
+ colorscale = [[0 , 'purple' ], [.5 , 'grey' ], [1 , 'white' ]],
2587
+ fontcolor = ['#000000' ], line_color = [], index_title = '' ,
2588
+ height_constant = 30 , showscale = False ,
2589
+ ** kwargs ):
2590
+ """
2591
+ BETA function that creates Plotly tables
2592
+ """
2593
+ # TODO: protected until #282
2594
+ from plotly .graph_objs import graph_objs
2595
+ # FigureFactory._validate_annotated_heatmap()
2596
+ table_matrix = _Table (z , index , colorscale , fontcolor , index_title ,
2597
+ ** kwargs ).get_table_matrix ()
2598
+ annotations = _Table (z , index , colorscale , fontcolor , index_title ,
2599
+ ** kwargs ).make_table_annotations ()
2600
+
2601
+ trace = dict (type = 'heatmap' ,
2602
+ z = table_matrix ,
2603
+ opacity = .7 ,
2604
+ colorscale = colorscale ,
2605
+ showscale = showscale ,
2606
+ ** kwargs )
2607
+
2608
+ data = [trace ]
2609
+ layout = dict (annotations = annotations ,
2610
+ height = len (table_matrix )* height_constant + 200 ,
2611
+ yaxis = dict (autorange = 'reversed' ,
2612
+ zeroline = False ,
2613
+ gridcolor = line_color ,
2614
+ gridwidth = 2 ,
2615
+ ticks = '' ,
2616
+ dtick = 1 ,
2617
+ tick0 = .5 ,
2618
+ showticklabels = False ),
2619
+ xaxis = dict (zeroline = False ,
2620
+ gridcolor = line_color ,
2621
+ gridwidth = 2 ,
2622
+ ticks = '' ,
2623
+ dtick = 1 ,
2624
+ tick0 = - 0.5 ,
2625
+ showticklabels = False ))
2626
+ return graph_objs .Figure (data = data , layout = layout )
2627
+
2512
2628
2513
2629
class _Quiver (FigureFactory ):
2514
2630
"""
@@ -3442,3 +3558,200 @@ def get_dendrogram_traces(self, X, colorscale):
3442
3558
trace_list .append (trace )
3443
3559
3444
3560
return trace_list , icoord , dcoord , ordered_labels , P ['leaves' ]
3561
+
3562
+
3563
+ class _AnnotatedHeatmap (FigureFactory ):
3564
+ """
3565
+ Refer to TraceFactory.create_annotated_heatmap() for docstring
3566
+ """
3567
+ def __init__ (self , z , x = [], y = [], text = [],
3568
+ fontcolor = [], colorscale = [],
3569
+ reversescale = False , ** kwargs ):
3570
+ from plotly .graph_objs import graph_objs
3571
+ self .z = z
3572
+ if x :
3573
+ self .x = x
3574
+ else :
3575
+ self .x = range (len (z [0 ]))
3576
+ if y :
3577
+ self .y = y
3578
+ else :
3579
+ self .y = range (len (z ))
3580
+ if text :
3581
+ self .text = text
3582
+ else :
3583
+ self .text = self .z
3584
+ if colorscale :
3585
+ self .colorscale = colorscale
3586
+ else :
3587
+ self .colorscale = 'RdBu'
3588
+ self .reversescale = reversescale
3589
+ self .fontcolor = fontcolor
3590
+
3591
+ def get_text_color (self ):
3592
+ '''
3593
+ Get font color for annotations.
3594
+
3595
+ The annotated heatmap can feature 2 text colors: min_color_text and max_color_text
3596
+ If no The user can define the text color for heatmap values >=
3597
+ (max_value - min_value)/2 and for heatmap values <
3598
+ (max_value - min_value)/2 Depending on the colorscale of the heatmap the text will be either
3599
+ :rtype (string, string) min_color_text, max_color_text: text
3600
+ color for the annotations
3601
+ '''
3602
+ colorscales = ['Greys' , 'Greens' , 'Blues' ,
3603
+ 'YIGnBu' , 'YIOrRd' , 'RdBu' ,
3604
+ 'Picnic' , 'Jet' , 'Hot' , 'Blackbody' ,
3605
+ 'Earth' , 'Electric' , 'Viridis' ]
3606
+ colorscales_opp = ['Reds' ]
3607
+ if self .fontcolor :
3608
+ min_color_text = self .fontcolor [0 ]
3609
+ max_color_text = self .fontcolor [- 1 ]
3610
+ elif self .colorscale in colorscales and self .reversescale :
3611
+ min_color_text = '#000000'
3612
+ max_color_text = '#FFFFFF'
3613
+ elif self .colorscale in colorscales :
3614
+ min_color_text = '#FFFFFF'
3615
+ max_color_text = '#000000'
3616
+ elif self .colorscale in colorscales_opp and self .reversescale :
3617
+ min_color_text = '#FFFFFF'
3618
+ max_color_text = '#000000'
3619
+ elif self .colorscale in colorscales_opp :
3620
+ min_color_text = '#000000'
3621
+ max_color_text = '#FFFFFF'
3622
+ elif isinstance (self .colorscale , list ):
3623
+ if 'rgb' in self .colorscale [0 ][1 ]:
3624
+ min_col = map (int ,
3625
+ self .colorscale [0 ][1 ].strip ('rgb()' ).split (',' ))
3626
+ max_col = map (int ,
3627
+ self .colorscale [- 1 ][1 ].strip ('rgb()' ).split (',' ))
3628
+ elif '#' in self .colorscale [0 ][1 ]:
3629
+ min_col = FigureFactory ._hex_to_rgb (self .colorscale [0 ][1 ])
3630
+ max_col = FigureFactory ._hex_to_rgb (self .colorscale [- 1 ][1 ])
3631
+ else :
3632
+ min_col = [255 , 255 , 255 ]
3633
+ max_col = [255 , 255 , 255 ]
3634
+
3635
+ if (min_col [0 ]* 0.299 + min_col [1 ]* 0.587 + min_col [2 ]* 0.114 ) > 186 :
3636
+ min_color_text = '#000000'
3637
+ else :
3638
+ min_color_text = '#FFFFFF'
3639
+ if (max_col [0 ]* 0.299 + max_col [1 ]* 0.587 + max_col [2 ]* 0.114 ) > 186 :
3640
+ max_color_text = '#000000'
3641
+ else :
3642
+ max_color_text = '#FFFFFF'
3643
+ else :
3644
+ min_color_text = '#000000'
3645
+ max_color_text = '#000000'
3646
+ return min_color_text , max_color_text
3647
+
3648
+ def make_annotations (self ):
3649
+ '''
3650
+ Generate annotations
3651
+
3652
+ :rtype (dict) annotations:
3653
+ '''
3654
+ from plotly .graph_objs import graph_objs
3655
+ min_color_text , max_color_text = _AnnotatedHeatmap .get_text_color (self )
3656
+ annotations = []
3657
+ for n , row in enumerate (self .text ):
3658
+ for m , val in enumerate (row ):
3659
+ annotations .append (
3660
+ graph_objs .Annotation (
3661
+ text = str (val ),
3662
+ x = self .x [m ],
3663
+ y = self .y [n ],
3664
+ xref = 'x1' ,
3665
+ yref = 'y1' ,
3666
+ font = dict (color = max_color_text if val >
3667
+ max (max (self .z )) / 2 else min_color_text ),
3668
+ showarrow = False ))
3669
+ return annotations
3670
+
3671
+
3672
+ class _Table (FigureFactory ):
3673
+ """
3674
+ Refer to TraceFactory.create_annotated_heatmap() for docstring
3675
+ """
3676
+ def __init__ (self , z , index , colorscale ,
3677
+ fontcolor , index_title = '' ,
3678
+ ** kwargs ):
3679
+ from plotly .graph_objs import graph_objs
3680
+ if _pandas_imported and isinstance (z , pd .DataFrame ):
3681
+ headers = z .columns .tolist ()
3682
+ z_index = z .index .tolist ()
3683
+ z = z .values .tolist ()
3684
+ z .insert (0 , headers )
3685
+ if index :
3686
+ z_index .insert (0 , index_title )
3687
+ for i in range (len (z )):
3688
+ z [i ].insert (0 , z_index [i ])
3689
+ self .z = z
3690
+ self .x = range (len (z [0 ]))
3691
+ self .y = range (len (z ))
3692
+ if colorscale :
3693
+ self .colorscale = colorscale
3694
+ else :
3695
+ self .colorscale = 'RdBu'
3696
+ self .fontcolor = fontcolor
3697
+ self .index = index
3698
+
3699
+ def get_table_matrix (self ):
3700
+ '''
3701
+ Create
3702
+
3703
+ :rtype (list[list] table_matrix):
3704
+ '''
3705
+ header = [0 ] * len (self .z [0 ])
3706
+ odd_row = [.5 ] * len (self .z [0 ])
3707
+ even_row = [1 ] * len (self .z [0 ])
3708
+ table_matrix = [None ] * len (self .z )
3709
+ table_matrix [0 ] = header
3710
+ for i in range (1 , len (self .z ), 2 ):
3711
+ table_matrix [i ] = odd_row
3712
+ for i in range (2 , len (self .z ), 2 ):
3713
+ table_matrix [i ] = even_row
3714
+ if self .index :
3715
+ for array in table_matrix :
3716
+ array [0 ] = 0
3717
+ return table_matrix
3718
+
3719
+ def get_table_fontcolor (self ):
3720
+ '''
3721
+ Make fontcolor array if a fontcolor array is not supplied.
3722
+ '''
3723
+ if len (self .fontcolor ) == 1 :
3724
+ self .fontcolor *= len (self .z )
3725
+ elif len (self .fontcolor ) == 3 :
3726
+ all_font_color = range (len (self .z ))
3727
+ all_font_color [0 ] = self .fontcolor [0 ]
3728
+ for i in range (1 , len (self .z ), 2 ):
3729
+ all_font_color [i ] = self .fontcolor [1 ]
3730
+ for i in range (2 , len (self .z ), 2 ):
3731
+ all_font_color [i ] = self .fontcolor [2 ]
3732
+ self .fontcolor = all_font_color
3733
+
3734
+ def make_table_annotations (self ):
3735
+ '''
3736
+ Generates annotations...
3737
+ '''
3738
+ from plotly .graph_objs import graph_objs
3739
+ table_matrix = _Table .get_table_matrix (self )
3740
+ _Table .get_table_fontcolor (self )
3741
+ annotations = []
3742
+ for n , row in enumerate (self .z ):
3743
+ for m , val in enumerate (row ):
3744
+ annotations .append (
3745
+ graph_objs .Annotation (
3746
+ text = ('<b>' + str (val ) + '</b>' if n < 1 or
3747
+ self .index and m < 1 else str (val )),
3748
+ x = self .x [m ] - .45 ,
3749
+ y = self .y [n ],
3750
+ xref = 'x1' ,
3751
+ yref = 'y1' ,
3752
+ align = "left" ,
3753
+ xanchor = "left" ,
3754
+ font = dict (color = self .fontcolor [n ]),
3755
+ showarrow = False ))
3756
+ return annotations
3757
+
0 commit comments