18
18
Tuple ,
19
19
Union ,
20
20
)
21
- from uuid import uuid1
21
+ from uuid import uuid4
22
22
23
23
import numpy as np
24
24
@@ -159,7 +159,7 @@ def __init__(
159
159
self .index = data .index
160
160
self .columns = data .columns
161
161
162
- self .uuid = uuid
162
+ self .uuid = uuid or ( uuid4 (). hex [: 6 ] + "_" )
163
163
self .table_styles = table_styles
164
164
self .caption = caption
165
165
if precision is None :
@@ -171,6 +171,11 @@ def __init__(
171
171
self .cell_ids = cell_ids
172
172
self .na_rep = na_rep
173
173
174
+ self .tooltip_styles = None # VERSION ADDED 1.X
175
+ self .tooltip_class = None
176
+ self .tooltip_class_styles = None
177
+ self .set_tooltip_class (name = 'pd-t' , properties = None )
178
+
174
179
# display_funcs maps (row, col) -> formatting function
175
180
176
181
def default_display_func (x ):
@@ -246,7 +251,7 @@ def _translate(self):
246
251
precision = self .precision
247
252
hidden_index = self .hidden_index
248
253
hidden_columns = self .hidden_columns
249
- uuid = self .uuid or str ( uuid1 ()). replace ( "-" , "_" )
254
+ uuid = self .uuid
250
255
ROW_HEADING_CLASS = "row_heading"
251
256
COL_HEADING_CLASS = "col_heading"
252
257
INDEX_NAME_CLASS = "index_name"
@@ -802,6 +807,124 @@ def where(
802
807
lambda val : value if cond (val ) else other , subset = subset , ** kwargs
803
808
)
804
809
810
+ def set_tooltips (self , ttips : DataFrame ):
811
+ """
812
+ Add string based tooltips that will appear in the `Styler` HTML result.
813
+
814
+ Parameters
815
+ ----------
816
+ ttips : DataFrame
817
+ DataFrame containing strings that will be translated to tooltips. Empty
818
+ strings, None, or NaN values will be ignored. DataFrame must have
819
+ identical rows and columns to the underlying `Styler` data.
820
+
821
+ Returns
822
+ -------
823
+ self : Styler
824
+
825
+ Notes
826
+ -----
827
+ Tooltips are created by adding `<span class="pd-t"></span>` to each data cell
828
+ and then manipulating the table level CSS to attach pseudo hover and pseudo after
829
+ selectors to produce the required the results. For styling control
830
+ see `:meth:Styler.set_tooltips_class`.
831
+ Tooltips are not designed to be efficient, and can add large amounts of additional
832
+ HTML for larger tables, since they also require that `cell_ids` is forced to `True`.
833
+
834
+ :param ttips:
835
+ :return:
836
+ """
837
+ if not (self .columns .equals (ttips .columns ) and self .index .equals (ttips .index )):
838
+ raise AttributeError ('Tooltips DataFrame must have identical column and index labelling to underlying.' )
839
+
840
+ self .cell_ids = True # tooltips only work with individual cell_ids
841
+ self .tooltip_styles = []
842
+ for i , rn in enumerate (ttips .index ):
843
+ for j , cn in enumerate (ttips .columns ):
844
+ if ttips .iloc [i , j ] in [np .nan , '' , None ]:
845
+ continue
846
+ else :
847
+ # add pseudo-class and pseudo-elements to css to create tips
848
+ self .tooltip_styles .extend ([
849
+ {'selector' : '#T_' + self .uuid + 'row' + str (i ) + '_col' + str (j ) + f':hover .{ self .tooltip_class } ' ,
850
+ 'props' : [('visibility' , 'visible' )]},
851
+ {'selector' : '#T_' + self .uuid + 'row' + str (i ) + '_col' + str (j ) + f' .{ self .tooltip_class } ::after' ,
852
+ 'props' : [('content' , f'"{ str (ttips .iloc [i , j ])} "' )]}])
853
+
854
+ return self
855
+
856
+ def set_tooltip_class (self , name = 'pd-t' , properties = None ):
857
+ """
858
+ Method to set the name and properties of the class for creating tooltips on hover.
859
+
860
+ Parameters
861
+ ----------
862
+ name : str, default 'pd-t'
863
+ Name of the tooltip class used in CSS, should conform to HTML standards.
864
+ properties : list-like, default None
865
+ List of (attr, value) tuples; see example. If `None` will use defaults.
866
+
867
+ Returns
868
+ -------
869
+ self : Styler
870
+
871
+ Notes
872
+ -----
873
+ Default properties for the tooltip class are as follows:
874
+
875
+ - visibility: hidden
876
+ - position: absolute
877
+ - z-index: 1
878
+ - background-color: black
879
+ - color: white
880
+ - transform: translate(-20px, -20px)
881
+
882
+ Examples
883
+ --------
884
+ >>> df = pd.DataFrame(np.random.randn(10, 4))
885
+ >>> df.style.set_tooltip_class(name='tt-add', properties=[
886
+ ... ('visibility', 'hidden'),
887
+ ... ('position', 'absolute'),
888
+ ... ('z-index', 1)])
889
+ """
890
+ if properties is None :
891
+ properties = [ # set default
892
+ ('visibility' , 'hidden' ),
893
+ ('position' , 'absolute' ),
894
+ ('z-index' , 1 ),
895
+ ('background-color' , 'black' ),
896
+ ('color' , 'white' ),
897
+ ('transform' , 'translate(-20px, -20px)' )
898
+ ]
899
+ self .tooltip_class = name
900
+
901
+ self .tooltip_class_styles = [
902
+ {'selector' : f'.{ self .tooltip_class } ' ,
903
+ 'props' : properties
904
+ }
905
+ ]
906
+ return self
907
+
908
+ def _render_tooltips (self , d ):
909
+ """
910
+ Mutate the render dictionary to allow for tooltips:
911
+
912
+ - Add `<span>` HTML element to each data cells `display_value`. Ignores headers.
913
+ - Add table level CSS styles to control pseudo classes.
914
+
915
+ Parameters
916
+ ----------
917
+ d : dict
918
+ The dictionary prior to rendering
919
+ """
920
+ if self .tooltip_styles :
921
+ for row in d ['body' ]:
922
+ for item in row :
923
+ if item ['type' ] == 'td' :
924
+ item ['display_value' ] = str (item ['display_value' ]) + f'<span class="{ self .tooltip_class } "></span>'
925
+ d ['table_styles' ].extend (self .tooltip_class_styles )
926
+ d ['table_styles' ].extend (self .tooltip_styles )
927
+
805
928
def set_precision (self , precision : int ) -> "Styler" :
806
929
"""
807
930
Set the precision used to render.
0 commit comments