@@ -64,8 +64,10 @@ def __init__(
6464 hidden_columns : list [str ] | None ,
6565 data_metrics : Mapping [str , DataMetric ] | None ,
6666 change_metrics : Mapping [str , ChangeMetric ] | None ,
67+ percentage_decimals : int ,
6768 ):
6869 self .slim = slim
70+ self .percentage_decimals = percentage_decimals
6971 self ._data = _compute_summary_data (
7072 comparison ,
7173 show_perfect_column_matches = show_perfect_column_matches ,
@@ -392,9 +394,13 @@ def _section_row_counts(self) -> RenderableType:
392394 if rows .n_left > 0 :
393395 fraction_rows_right = rows .n_right / rows .n_left
394396 if fraction_rows_right > 1 :
395- gain_loss = f"(+{ (fraction_rows_right - 1 ):.2%} )"
397+ gain_loss = (
398+ f"(+{ (fraction_rows_right - 1 ):.{self .percentage_decimals }%} )"
399+ )
396400 elif fraction_rows_right < 1 :
397- gain_loss = f"(-{ (1 - fraction_rows_right ):.2%} )"
401+ gain_loss = (
402+ f"(-{ (1 - fraction_rows_right ):.{self .percentage_decimals }%} )"
403+ )
398404 else :
399405 gain_loss = "(no change)"
400406
@@ -424,6 +430,7 @@ def _section_row_matches(self) -> RenderableType:
424430 assert rows .n_joined_unequal is not None
425431 assert rows .n_right_only is not None
426432 n_joined = rows .n_joined_equal + rows .n_joined_unequal
433+ decimals = self .percentage_decimals
427434
428435 columns : list [RenderableType ] = []
429436 num_dummy_cols = 5
@@ -512,31 +519,31 @@ def _section_row_matches(self) -> RenderableType:
512519 grid .add_row (
513520 f"{ rows .n_left_only :,} " ,
514521 f"{ self ._data ._truncated_left_name } only" ,
515- f"({ _format_fraction_as_percentage (fraction_left_only )} )" ,
522+ f"({ _format_fraction_as_percentage (fraction_left_only , decimals )} )" ,
516523 )
517524 grid .add_section ()
518525 if rows .n_joined_equal > 0 :
519526 fraction_equal = rows .n_joined_equal / n_joined
520527 grid .add_row (
521528 f"{ rows .n_joined_equal :,} " ,
522529 "equal" ,
523- f"({ _format_fraction_as_percentage (fraction_equal )} )" ,
530+ f"({ _format_fraction_as_percentage (fraction_equal , decimals )} )" ,
524531 )
525532 grid .add_section ()
526533 if rows .n_joined_unequal > 0 :
527534 fraction_unequal = rows .n_joined_unequal / n_joined
528535 grid .add_row (
529536 f"{ rows .n_joined_unequal :,} " ,
530537 "unequal" ,
531- f"({ _format_fraction_as_percentage (fraction_unequal )} )" ,
538+ f"({ _format_fraction_as_percentage (fraction_unequal , decimals )} )" ,
532539 )
533540 grid .add_section ()
534541 if rows .n_right_only > 0 :
535542 fraction_right_only = rows .n_right_only / rows .n_right
536543 grid .add_row (
537544 f"{ rows .n_right_only :,} " ,
538545 f"{ self ._data ._truncated_right_name } only" ,
539- f"({ _format_fraction_as_percentage (fraction_right_only )} )" ,
546+ f"({ _format_fraction_as_percentage (fraction_right_only , decimals )} )" ,
540547 )
541548 columns .append (grid )
542549
@@ -594,10 +601,11 @@ def _section_columns(self) -> RenderableType:
594601 if has_top_changes_column :
595602 matches .add_column ("Top Changes" , justify = "right" )
596603 max_col_len = max (len (c .name ) for c in columns )
604+ decimals = self .percentage_decimals
597605 for col in columns :
598606 row_items : list [RenderableType ] = [
599607 Text (col .name , style = "cyan" ),
600- f"{ _format_fraction_as_percentage (col .match_rate )} " ,
608+ f"{ _format_fraction_as_percentage (col .match_rate , decimals )} " ,
601609 ]
602610 for label in self ._data ._change_metric_labels :
603611 value = (
@@ -1228,22 +1236,24 @@ def _format_colname(name: str) -> str:
12281236 return f"[cyan]{ name } [/cyan]"
12291237
12301238
1231- def _format_fraction_as_percentage (fraction : float ) -> str :
1232- """Format a fraction as a percentage with two decimal places.
1239+ def _format_fraction_as_percentage (fraction : float , decimals : int ) -> str :
1240+ """Format a fraction as a percentage with the given number of decimal places.
12331241
12341242 Only shows 0%/100% if the fraction is exactly 0 or 1, respectively.
12351243
12361244 Args:
12371245 fraction: The fraction to format as a percentage. Must be in the range [0, 1].
1246+ decimals: The number of decimal places to show.
12381247
12391248 Returns:
12401249 The formatted percentage, including a percent sign.
12411250 """
12421251 assert 0 <= fraction <= 1 , "Fraction must be between 0 and 1"
12431252 percentage = fraction * 100
12441253 if percentage not in [0 , 100 ]:
1245- percentage = min (max (percentage , 0.01 ), 99.99 )
1246- return f"{ percentage :.2f} %"
1254+ smallest = 10 ** - decimals
1255+ percentage = min (max (percentage , smallest ), 100 - smallest )
1256+ return f"{ percentage :.{decimals }f} %"
12471257
12481258
12491259def _yellow (raw : Any ) -> str :
0 commit comments