@@ -632,10 +632,10 @@ def get_tabular_report(self) -> GT:
632632
633633 # Iterate over each column's data and obtain a dictionary of statistics for each column
634634 for idx , col in enumerate (column_data ):
635- if "statistics" in col and (
636- "numerical" in col [ "statistics" ] or "string_lengths" in col [ "statistics" ]
637- ) :
638- col_dict = _process_numerical_string_column_data (col )
635+ if "statistics" in col and "numerical" in col [ "statistics" ]:
636+ col_dict = _process_numerical_column_data ( col )
637+ elif "statistics" in col and "string_lengths" in col [ "statistics" ] :
638+ col_dict = _process_string_column_data (col )
639639 elif "statistics" in col and "datetime" in col ["statistics" ]:
640640 col_dict = _process_datetime_column_data (col )
641641 datetime_row_list .append (idx )
@@ -724,13 +724,11 @@ def get_tabular_report(self) -> GT:
724724 )
725725 .tab_style (
726726 style = style .borders (sides = "left" , color = "#D3D3D3" , style = "solid" ),
727- locations = loc .body (columns = ["missing_vals" , "mean" , "iqr" ]),
727+ locations = loc .body (columns = ["missing_vals" , "mean" , "min" , " iqr" ]),
728728 )
729729 .tab_style (
730730 style = style .borders (sides = "left" , color = "#E5E5E5" , style = "dashed" ),
731- locations = loc .body (
732- columns = ["std_dev" , "min" , "p05" , "q_1" , "med" , "q_3" , "p95" , "max" ]
733- ),
731+ locations = loc .body (columns = ["std_dev" , "p05" , "q_1" , "med" , "q_3" , "p95" , "max" ]),
734732 )
735733 .tab_style (
736734 style = style .borders (sides = "left" , style = "none" ),
@@ -743,20 +741,31 @@ def get_tabular_report(self) -> GT:
743741 style = style .fill (color = "#FCFCFC" ),
744742 locations = loc .body (columns = ["missing_vals" , "unique_vals" , "iqr" ]),
745743 )
744+ .tab_style (
745+ style = style .text (align = "center" ), locations = loc .column_labels (columns = stat_columns )
746+ )
746747 .cols_label (
747748 column_number = "" ,
748749 icon = "" ,
749750 column_name = "Column" ,
750- missing_vals = "NAs " ,
751- unique_vals = "Uniq. " ,
751+ missing_vals = "NA " ,
752+ unique_vals = "UQ " ,
752753 mean = "Mean" ,
753- std_dev = "S.D. " ,
754+ std_dev = "SD " ,
754755 min = "Min" ,
755- p05 = "P05" ,
756- q_1 = "Q1" ,
756+ p05 = html (
757+ 'P<span style="font-size: 0.75em; vertical-align: sub; position: relative; line-height: 0.5em;">5</span>'
758+ ),
759+ q_1 = html (
760+ 'Q<span style="font-size: 0.75em; vertical-align: sub; position: relative; line-height: 0.5em;">1</span>'
761+ ),
757762 med = "Med" ,
758- q_3 = "Q3" ,
759- p95 = "P95" ,
763+ q_3 = html (
764+ 'Q<span style="font-size: 0.75em; vertical-align: sub; position: relative; line-height: 0.5em;">3</span>'
765+ ),
766+ p95 = html (
767+ 'P<span style="font-size: 0.75em; vertical-align: sub; position: relative; line-height: 0.5em;">95</span>'
768+ ),
760769 max = "Max" ,
761770 iqr = "IQR" ,
762771 )
@@ -910,10 +919,12 @@ def _compact_decimal_fmt(value: float | int) -> str:
910919 formatted = fmt_number (value , decimals = 2 )[0 ]
911920 elif abs (value ) < 0.01 :
912921 formatted = fmt_scientific (value , decimals = 1 , exp_style = "E1" )[0 ]
913- elif abs (value ) >= 1 and abs (value ) < 1000 :
922+ elif abs (value ) >= 1 and abs (value ) < 10 :
923+ formatted = fmt_number (value , decimals = 2 , use_seps = False )[0 ]
924+ elif abs (value ) >= 10 and abs (value ) < 1000 :
914925 formatted = fmt_number (value , n_sigfig = 3 )[0 ]
915926 elif abs (value ) >= 1000 and abs (value ) < 10_000 :
916- formatted = fmt_number (value , decimals = 0 , use_seps = False )[0 ]
927+ formatted = fmt_number (value , n_sigfig = 4 , use_seps = False )[0 ]
917928 else :
918929 formatted = fmt_scientific (value , decimals = 1 , exp_style = "E1" )[0 ]
919930
@@ -937,7 +948,7 @@ def _compact_0_1_fmt(value: float | int) -> str:
937948 return formatted
938949
939950
940- def _process_numerical_string_column_data (column_data : dict ) -> dict :
951+ def _process_numerical_column_data (column_data : dict ) -> dict :
941952 column_number = column_data ["column_number" ]
942953 column_name = column_data ["column_name" ]
943954 column_type = column_data ["column_type" ]
@@ -947,26 +958,18 @@ def _process_numerical_string_column_data(column_data: dict) -> dict:
947958 f"<div style='font-size: 11px; color: gray;'>{ column_type } </div>"
948959 )
949960
950- # Determine if the column is a numerical or string column
951- if "numerical" in column_data ["statistics" ]:
952- key = "numerical"
953- icon = "numeric"
954- elif "string_lengths" in column_data ["statistics" ]:
955- key = "string_lengths"
956- icon = "string"
957-
958961 # Get the Missing and Unique value counts and fractions
959962 missing_vals = column_data ["n_missing_values" ]
960963 unique_vals = column_data ["n_unique_values" ]
961- missing_vals_frac = _compact_decimal_fmt (column_data ["f_missing_values" ])
962- unique_vals_frac = _compact_decimal_fmt (column_data ["f_unique_values" ])
964+ missing_vals_frac = _compact_0_1_fmt (column_data ["f_missing_values" ])
965+ unique_vals_frac = _compact_0_1_fmt (column_data ["f_unique_values" ])
963966
964967 missing_vals_str = f"{ missing_vals } <br>{ missing_vals_frac } "
965968 unique_vals_str = f"{ unique_vals } <br>{ unique_vals_frac } "
966969
967970 # Get the descriptive and quantile statistics
968- descriptive_stats = column_data ["statistics" ][key ]["descriptive" ]
969- quantile_stats = column_data ["statistics" ][key ]["quantiles" ]
971+ descriptive_stats = column_data ["statistics" ]["numerical" ]["descriptive" ]
972+ quantile_stats = column_data ["statistics" ]["numerical" ]["quantiles" ]
970973
971974 # Get all values from the descriptive and quantile stats into a single list
972975 quantile_stats_vals = [v [1 ] for v in quantile_stats .items ()]
@@ -1000,7 +1003,7 @@ def _process_numerical_string_column_data(column_data: dict) -> dict:
10001003 # Create a single dictionary with the statistics for the column
10011004 stats_dict = {
10021005 "column_number" : column_number ,
1003- "icon" : SVG_ICONS_FOR_DATA_TYPES [icon ],
1006+ "icon" : SVG_ICONS_FOR_DATA_TYPES ["numeric" ],
10041007 "column_name" : column_name_and_type ,
10051008 "missing_vals" : missing_vals_str ,
10061009 "unique_vals" : unique_vals_str ,
@@ -1011,6 +1014,68 @@ def _process_numerical_string_column_data(column_data: dict) -> dict:
10111014 return stats_dict
10121015
10131016
1017+ def _process_string_column_data (column_data : dict ) -> dict :
1018+ column_number = column_data ["column_number" ]
1019+ column_name = column_data ["column_name" ]
1020+ column_type = column_data ["column_type" ]
1021+
1022+ column_name_and_type = (
1023+ f"<div style='font-size: 13px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;'>{ column_name } </div>"
1024+ f"<div style='font-size: 11px; color: gray;'>{ column_type } </div>"
1025+ )
1026+
1027+ # Get the Missing and Unique value counts and fractions
1028+ missing_vals = column_data ["n_missing_values" ]
1029+ unique_vals = column_data ["n_unique_values" ]
1030+ missing_vals_frac = _compact_0_1_fmt (column_data ["f_missing_values" ])
1031+ unique_vals_frac = _compact_0_1_fmt (column_data ["f_unique_values" ])
1032+
1033+ missing_vals_str = f"{ missing_vals } <br>{ missing_vals_frac } "
1034+ unique_vals_str = f"{ unique_vals } <br>{ unique_vals_frac } "
1035+
1036+ # Get the descriptive and quantile statistics
1037+ descriptive_stats = column_data ["statistics" ]["string_lengths" ]["descriptive" ]
1038+ quantile_stats = column_data ["statistics" ]["string_lengths" ]["quantiles" ]
1039+
1040+ # Format the descriptive statistics (mean and standard deviation)
1041+ for key , value in descriptive_stats .items ():
1042+ formatted_val = _compact_decimal_fmt (value = value )
1043+ descriptive_stats [key ] = (
1044+ f'<div><div>{ formatted_val } </div><div style="float: left; position: absolute;">'
1045+ '<div title="string length measure" style="font-size: 7px; color: #999; '
1046+ 'font-style: italic; cursor: help;">SL</div></div></div>'
1047+ )
1048+
1049+ # Format the quantile statistics
1050+ for key , value in quantile_stats .items ():
1051+ formatted_val = _compact_integer_fmt (value = value )
1052+ quantile_stats [key ] = (
1053+ f'<div><div>{ formatted_val } </div><div style="float: left; position: absolute;">'
1054+ '<div title="string length measure" style="font-size: 7px; color: #999; '
1055+ 'font-style: italic; cursor: help;">SL</div></div></div>'
1056+ )
1057+
1058+ # Create a single dictionary with the statistics for the column
1059+ stats_dict = {
1060+ "column_number" : column_number ,
1061+ "icon" : SVG_ICONS_FOR_DATA_TYPES ["string" ],
1062+ "column_name" : column_name_and_type ,
1063+ "missing_vals" : missing_vals_str ,
1064+ "unique_vals" : unique_vals_str ,
1065+ ** descriptive_stats ,
1066+ "min" : quantile_stats ["min" ],
1067+ "p05" : "—" ,
1068+ "q_1" : "—" ,
1069+ "med" : quantile_stats ["med" ],
1070+ "q_3" : "—" ,
1071+ "p95" : "—" ,
1072+ "max" : quantile_stats ["max" ],
1073+ "iqr" : "—" ,
1074+ }
1075+
1076+ return stats_dict
1077+
1078+
10141079def _process_datetime_column_data (column_data : dict ) -> dict :
10151080 column_number = column_data ["column_number" ]
10161081 column_name = column_data ["column_name" ]
@@ -1031,8 +1096,8 @@ def _process_datetime_column_data(column_data: dict) -> dict:
10311096 # Get the Missing and Unique value counts and fractions
10321097 missing_vals = column_data ["n_missing_values" ]
10331098 unique_vals = column_data ["n_unique_values" ]
1034- missing_vals_frac = _compact_decimal_fmt (column_data ["f_missing_values" ])
1035- unique_vals_frac = _compact_decimal_fmt (column_data ["f_unique_values" ])
1099+ missing_vals_frac = _compact_0_1_fmt (column_data ["f_missing_values" ])
1100+ unique_vals_frac = _compact_0_1_fmt (column_data ["f_unique_values" ])
10361101
10371102 missing_vals_str = f"{ missing_vals } <br>{ missing_vals_frac } "
10381103 unique_vals_str = f"{ unique_vals } <br>{ unique_vals_frac } "
@@ -1076,9 +1141,9 @@ def _process_boolean_column_data(column_data: dict) -> dict:
10761141 f"<div style='font-size: 11px; color: gray;'>{ column_type } </div>"
10771142 )
10781143
1079- # Get the Missing and Unique value counts and fractions
1144+ # Get the missing value count and fraction
10801145 missing_vals = column_data ["n_missing_values" ]
1081- missing_vals_frac = _compact_decimal_fmt (column_data ["f_missing_values" ])
1146+ missing_vals_frac = _compact_0_1_fmt (column_data ["f_missing_values" ])
10821147 missing_vals_str = f"{ missing_vals } <br>{ missing_vals_frac } "
10831148
10841149 # Get the fractions of True and False values
@@ -1088,10 +1153,12 @@ def _process_boolean_column_data(column_data: dict) -> dict:
10881153 true_vals_frac_fmt = _compact_0_1_fmt (f_true_values )
10891154 false_vals_frac_fmt = _compact_0_1_fmt (f_false_values )
10901155
1091- # Create an HTML string that combines fractions for the True and False values
1092- true_false_vals_str = f"<span style='font-weight: bold;'>T</span>{ true_vals_frac_fmt } <br><span style='font-weight: bold;'>F</span>{ false_vals_frac_fmt } "
1093-
1094- # unique_vals_str = f"{unique_vals}<br>{unique_vals_frac}"
1156+ # Create an HTML string that combines fractions for the True and False values; this will be
1157+ # used in the Unique Vals column of the report table
1158+ true_false_vals_str = (
1159+ f"<span style='font-weight: bold;'>T</span>{ true_vals_frac_fmt } <br>"
1160+ f"<span style='font-weight: bold;'>F</span>{ false_vals_frac_fmt } "
1161+ )
10951162
10961163 # Create a single dictionary with the statistics for the column
10971164 stats_dict = {
0 commit comments