Repository: deepchecks/deepchecks

Issue:
[DOCS] Data Duplicates example improvement
Please follow the guidelines from this issue: #543 to improve it


Discussion:

Resolving patch:
diff --git a/deepchecks/checks/integrity/data_duplicates.py b/deepchecks/checks/integrity/data_duplicates.py
--- a/deepchecks/checks/integrity/data_duplicates.py
+++ b/deepchecks/checks/integrity/data_duplicates.py
@@ -26,7 +26,7 @@
 
 
 class DataDuplicates(SingleDatasetBaseCheck):
-    """Search for duplicate data in dataset.
+    """Checks for duplicate samples in the dataset.
 
     Args:
         columns (Hashable, Iterable[Hashable]):
@@ -102,7 +102,7 @@ def run(self, dataset: Dataset, model=None) -> CheckResult:
 
             most_duplicates = most_duplicates.set_index(['Instances', 'Number of Duplicates'])
 
-            text = f'{format_percent(percent_duplicate)} of data samples are duplicates'
+            text = f'{format_percent(percent_duplicate)} of data samples are duplicates. '
             explanation = 'Each row in the table shows an example of duplicate data and the number of times it appears.'
             display = [text, explanation, most_duplicates]
 
diff --git a/deepchecks/utils/strings.py b/deepchecks/utils/strings.py
--- a/deepchecks/utils/strings.py
+++ b/deepchecks/utils/strings.py
@@ -232,12 +232,19 @@ def split_by_order(s: str, separators: t.Iterable[str], keep: bool = True) -> t.
     return split_s
 
 
-def format_percent(ratio: float, floating_point: int = 2) -> str:
+def truncate_zero_percent(ratio: float, floating_point: int):
+    """Display ratio as percent without trailing zeros."""
+    return f'{ratio * 100:.{floating_point}f}'.rstrip('0').rstrip('.') + '%'
+
+
+def format_percent(ratio: float, floating_point: int = 2, scientific_notation_threshold: int = 4) -> str:
     """Format percent for elegant display.
 
     Args:
         ratio (float): Ratio to be displayed as percent
         floating_point (int): Number of floating points to display
+        scientific_notation_threshold (int): Number of digits after the decimal to consider before
+                                             switching to scientific notation
 
     Returns:
         String of ratio as percent
@@ -252,16 +259,19 @@ def format_percent(ratio: float, floating_point: int = 2) -> str:
     if int(ratio) == ratio:
         result = f'{int(ratio) * 100}%'
     elif ratio > 1:
-        result = f'{ratio * 100:.{floating_point}f}%'
+        result = truncate_zero_percent(ratio, floating_point)
     elif ratio < 10**(-(2+floating_point)):
-        result = f'{Decimal(ratio * 100):.{floating_point}E}%'
+        if ratio > 10**(-(2+scientific_notation_threshold)):
+            result = truncate_zero_percent(ratio, scientific_notation_threshold)
+        else:
+            result = f'{Decimal(ratio * 100):.{floating_point}E}%'
     elif ratio > (1-10**(-(2+floating_point))):
         if floating_point > 0:
             result = f'99.{"".join(["9"]*floating_point)}%'
         else:
             result = '99%'
     else:
-        result = f'{ratio:.{floating_point}%}'
+        result = truncate_zero_percent(ratio, floating_point)
 
     return prefix + result
 


Test patch:
diff --git a/tests/checks/distribution/trust_score_comparison_test.py b/tests/checks/distribution/trust_score_comparison_test.py
--- a/tests/checks/distribution/trust_score_comparison_test.py
+++ b/tests/checks/distribution/trust_score_comparison_test.py
@@ -88,7 +88,7 @@ def test_condition_mean_score_percent_decline_fail():
     # Assert
     assert_that(condition_result, equal_condition_result(
         is_pass=False,
-        name='Mean trust score decline is not greater than 10.00%',
+        name='Mean trust score decline is not greater than 10%',
         details='Found decline of: -33.33%',
         category=ConditionCategory.WARN
     ))
@@ -105,7 +105,7 @@ def test_condition_mean_score_percent_decline_pass():
     # Assert
     assert_that(condition_result, equal_condition_result(
         is_pass=True,
-        name='Mean trust score decline is not greater than 40.00%'
+        name='Mean trust score decline is not greater than 40%'
     ))
 
 
diff --git a/tests/checks/integrity/data_duplicate_test.py b/tests/checks/integrity/data_duplicate_test.py
--- a/tests/checks/integrity/data_duplicate_test.py
+++ b/tests/checks/integrity/data_duplicate_test.py
@@ -121,8 +121,8 @@ def test_condition_fail():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               details='Found 40.00% duplicate data',
-                               name='Duplicate data ratio is not greater than 10.00%',
+                               details='Found 40% duplicate data',
+                               name='Duplicate data ratio is not greater than 10%',
                                category=ConditionCategory.WARN)))
 
 
diff --git a/tests/checks/integrity/dominant_frequency_change_test.py b/tests/checks/integrity/dominant_frequency_change_test.py
--- a/tests/checks/integrity/dominant_frequency_change_test.py
+++ b/tests/checks/integrity/dominant_frequency_change_test.py
@@ -175,9 +175,9 @@ def test_condition_ratio_of_change_not_greater_than_not_passed(iris_split_datase
     # Assert
     assert_that(result, equal_condition_result(
             is_pass=False,
-            name='Change in ratio of dominant value in data is not greater than 5.00%',
+            name='Change in ratio of dominant value in data is not greater than 5%',
             details='Found columns with % difference in dominant value above threshold: '
-                    '{\'sepal width (cm)\': \'8.00%\'}'
+                    '{\'sepal width (cm)\': \'8%\'}'
     ))
 
 
@@ -193,5 +193,5 @@ def test_condition_ratio_of_change_not_greater_than_passed(iris_split_dataset_an
     # Assert
     assert_that(result, has_items(
         equal_condition_result(is_pass=True,
-                               name='Change in ratio of dominant value in data is not greater than 25.00%')
+                               name='Change in ratio of dominant value in data is not greater than 25%')
     ))
\ No newline at end of file
diff --git a/tests/checks/integrity/label_ambiguity_test.py b/tests/checks/integrity/label_ambiguity_test.py
--- a/tests/checks/integrity/label_ambiguity_test.py
+++ b/tests/checks/integrity/label_ambiguity_test.py
@@ -89,7 +89,7 @@ def test_label_ambiguity_condition():
     # Assert
     assert_that(condition_result, has_items(
         equal_condition_result(is_pass=False,
-                               details='Found ratio of samples with multiple labels above threshold: 50.00%',
+                               details='Found ratio of samples with multiple labels above threshold: 50%',
                                name='Ambiguous sample ratio is not greater than 0%')
     ))
 
@@ -112,5 +112,5 @@ def test_label_ambiguity_condition_pass():
     # Assert
     assert_that(condition_result, has_items(
         equal_condition_result(is_pass=True,
-                               name='Ambiguous sample ratio is not greater than 70.00%')
+                               name='Ambiguous sample ratio is not greater than 70%')
     ))
diff --git a/tests/checks/integrity/mixed_data_types_test.py b/tests/checks/integrity/mixed_data_types_test.py
--- a/tests/checks/integrity/mixed_data_types_test.py
+++ b/tests/checks/integrity/mixed_data_types_test.py
@@ -123,8 +123,8 @@ def test_condition_pass_all_columns():
     result = check.conditions_decision(check.run(dataframe))
     # Assert
     assert_that(result, has_items(
-        equal_condition_result(is_pass=True, name='Rare data types in column are either more than 10.00% or less '
-                                                  'than 1.00% of the data')
+        equal_condition_result(is_pass=True, name='Rare data types in column are either more than 10% or less '
+                                                  'than 1% of the data')
     ))
 
 
@@ -138,8 +138,8 @@ def test_condition_pass_fail_single_column():
     # Assert
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               name='Rare data types in column are either more than 40.00% or less '
-                                    'than 1.00% of the data',
+                               name='Rare data types in column are either more than 40% or less '
+                                    'than 1% of the data',
                                details='Found columns with non-negligible quantities of samples with a different '
                                        'data type from the majority of samples: [\'col1\']',
                                category=ConditionCategory.WARN)
@@ -156,8 +156,8 @@ def test_condition_pass_fail_ignore_column():
     # Assert
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               name='Rare data types in column are either more than 40.00% or'
-                                    ' less than 1.00% of the data',
+                               name='Rare data types in column are either more than 40% or'
+                                    ' less than 1% of the data',
                                details='Found columns with non-negligible quantities of samples with a different '
                                        'data type from the majority of samples: [\'col1\']',
                                category=ConditionCategory.WARN)
diff --git a/tests/checks/integrity/new_category_test.py b/tests/checks/integrity/new_category_test.py
--- a/tests/checks/integrity/new_category_test.py
+++ b/tests/checks/integrity/new_category_test.py
@@ -215,8 +215,8 @@ def test_condition_count_fail():
     assert_that(result, has_items(
         equal_condition_result(
             is_pass=False,
-            details='Found columns with ratio of new category samples above threshold: {\'col1\': \'25.00%\'}',
-            name='Ratio of samples with a new category is not greater than 10.00%')
+            details='Found columns with ratio of new category samples above threshold: {\'col1\': \'25%\'}',
+            name='Ratio of samples with a new category is not greater than 10%')
     ))
 
 
@@ -235,5 +235,5 @@ def test_condition_count_pass():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=True,
-                               name='Ratio of samples with a new category is not greater than 30.00%')
+                               name='Ratio of samples with a new category is not greater than 30%')
     ))
diff --git a/tests/checks/integrity/new_label_test.py b/tests/checks/integrity/new_label_test.py
--- a/tests/checks/integrity/new_label_test.py
+++ b/tests/checks/integrity/new_label_test.py
@@ -178,7 +178,7 @@ def test_condition_ratio_of_new_label_samples_pass():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=True,
-                               name='Ratio of samples with new label is not greater than 30.00%')
+                               name='Ratio of samples with new label is not greater than 30%')
     ))
 
 
@@ -198,6 +198,6 @@ def test_condition_ratio_of_new_label_samples_fail():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               details='Found new labels in test data: [5]\nmaking 25.00% of samples.',
-                               name='Ratio of samples with new label is not greater than 10.00%')
+                               details='Found new labels in test data: [5]\nmaking 25% of samples.',
+                               name='Ratio of samples with new label is not greater than 10%')
     ))
diff --git a/tests/checks/integrity/special_chars_test.py b/tests/checks/integrity/special_chars_test.py
--- a/tests/checks/integrity/special_chars_test.py
+++ b/tests/checks/integrity/special_chars_test.py
@@ -153,7 +153,7 @@ def test_condition_fail_all(diabetes_split_dataset_and_model):
     # Assert
     assert_that(results, has_items(equal_condition_result(
         is_pass=False,
-        name='Ratio of entirely special character samples not greater than 0.10%',
+        name='Ratio of entirely special character samples not greater than 0.1%',
         details='Found columns with ratio above threshold: {\'age\': \'34.12%\', \'sex\': \'34.12%\', '
                 '\'bmi\': \'34.12%\', \'bp\': \'34.12%\'}',
         category=ConditionCategory.WARN
@@ -174,7 +174,7 @@ def test_condition_fail_some(diabetes_split_dataset_and_model):
     # Assert
     assert_that(results, has_items(equal_condition_result(
         is_pass=False,
-        name='Ratio of entirely special character samples not greater than 30.00%',
+        name='Ratio of entirely special character samples not greater than 30%',
         details='Found columns with ratio above threshold: {\'sex\': \'34.12%\', \'bmi\': \'34.12%\'}',
         category=ConditionCategory.WARN
     )))
@@ -191,5 +191,5 @@ def test_condition_pass(diabetes_split_dataset_and_model):
     # Assert
     assert_that(results, has_items(equal_condition_result(
         is_pass=True,
-        name='Ratio of entirely special character samples not greater than 0.10%',
+        name='Ratio of entirely special character samples not greater than 0.1%',
     )))
diff --git a/tests/checks/integrity/string_length_out_of_bounds_test.py b/tests/checks/integrity/string_length_out_of_bounds_test.py
--- a/tests/checks/integrity/string_length_out_of_bounds_test.py
+++ b/tests/checks/integrity/string_length_out_of_bounds_test.py
@@ -175,7 +175,7 @@ def test_condition_ratio_fail():
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
                                details='Found columns with outliers ratio above threshold: {\'col1\': \'0.99%\'}',
-                               name='Ratio of outliers not greater than 0.10% string length outliers',
+                               name='Ratio of outliers not greater than 0.1% string length outliers',
                                category=ConditionCategory.WARN)
     ))
 
@@ -195,5 +195,5 @@ def test_condition_ratio_pass():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=True,
-                               name='Ratio of outliers not greater than 10.00% string length outliers')
+                               name='Ratio of outliers not greater than 10% string length outliers')
     ))
diff --git a/tests/checks/integrity/string_mismatch_comparison_test.py b/tests/checks/integrity/string_mismatch_comparison_test.py
--- a/tests/checks/integrity/string_mismatch_comparison_test.py
+++ b/tests/checks/integrity/string_mismatch_comparison_test.py
@@ -142,8 +142,8 @@ def test_condition_percent_new_variants_fail():
     # Assert
     assert_that(result, equal_condition_result(
         is_pass=False,
-        name='Ratio of new variants in test data is not greater than 10.00%',
-        details='Found columns with ratio of variants above threshold: {\'col1\': \'25.00%\'}'
+        name='Ratio of new variants in test data is not greater than 10%',
+        details='Found columns with ratio of variants above threshold: {\'col1\': \'25%\'}'
     ))
 
 
@@ -157,7 +157,7 @@ def test_condition_percent_new_variants_pass():
     # Assert
     assert_that(result, has_items(
         equal_condition_result(is_pass=True,
-                               name='Ratio of new variants in test data is not greater than 50.00%')
+                               name='Ratio of new variants in test data is not greater than 50%')
     ))
 
 
diff --git a/tests/checks/integrity/string_mismatch_test.py b/tests/checks/integrity/string_mismatch_test.py
--- a/tests/checks/integrity/string_mismatch_test.py
+++ b/tests/checks/integrity/string_mismatch_test.py
@@ -140,8 +140,8 @@ def test_condition_percent_variants_no_more_than_fail():
     # Assert
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               name='Ratio of variants is not greater than 10.00%',
-                               details='Found columns with variants ratio above threshold: {\'col1\': \'75.00%\'}')
+                               name='Ratio of variants is not greater than 10%',
+                               details='Found columns with variants ratio above threshold: {\'col1\': \'75%\'}')
     ))
 
 
@@ -155,7 +155,7 @@ def test_condition_percent_variants_no_more_than_pass():
     # Assert
     assert_that(result, has_items(
         equal_condition_result(is_pass=True,
-                               name='Ratio of variants is not greater than 50.00%')
+                               name='Ratio of variants is not greater than 50%')
     ))
 
 
diff --git a/tests/checks/methodology/boosting_overfit_test.py b/tests/checks/methodology/boosting_overfit_test.py
--- a/tests/checks/methodology/boosting_overfit_test.py
+++ b/tests/checks/methodology/boosting_overfit_test.py
@@ -114,7 +114,7 @@ def test_condition_score_decline_not_greater_than_pass(diabetes, diabetes_model)
     # Assert
     assert_that(condition_result, equal_condition_result(
         is_pass=True,
-        name='Test score over iterations doesn\'t decline by more than 5.00% from the best score'
+        name='Test score over iterations doesn\'t decline by more than 5% from the best score'
     ))
 
 
@@ -129,6 +129,6 @@ def test_condition_score_percentage_decline_not_greater_than_not_pass(diabetes,
     # Assert
     assert_that(condition_result, equal_condition_result(
         is_pass=False,
-        name='Test score over iterations doesn\'t decline by more than 1.00% from the best score',
+        name='Test score over iterations doesn\'t decline by more than 1% from the best score',
         details='Found score decline above threshold: -3.64%'
     ))
diff --git a/tests/checks/methodology/date_leakage_test.py b/tests/checks/methodology/date_leakage_test.py
--- a/tests/checks/methodology/date_leakage_test.py
+++ b/tests/checks/methodology/date_leakage_test.py
@@ -254,7 +254,7 @@ def test_condition_fail_on_overlap():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               name='Date leakage ratio is not greater than 20.00%',
+                               name='Date leakage ratio is not greater than 20%',
                                details='Found 27.27% leaked dates')
     ))
 
@@ -299,7 +299,7 @@ def test_condition_fail_on_overlap_date_in_index():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               name='Date leakage ratio is not greater than 20.00%',
+                               name='Date leakage ratio is not greater than 20%',
                                details='Found 27.27% leaked dates')
     ))
 
@@ -384,7 +384,7 @@ def test_condition_fail_on_duplicates():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               name='Date leakage ratio is not greater than 10.00%',
+                               name='Date leakage ratio is not greater than 10%',
                                details='Found 18.18% leaked dates')
     ))
 
diff --git a/tests/checks/methodology/index_train_val_leakage_test.py b/tests/checks/methodology/index_train_val_leakage_test.py
--- a/tests/checks/methodology/index_train_val_leakage_test.py
+++ b/tests/checks/methodology/index_train_val_leakage_test.py
@@ -78,8 +78,8 @@ def test_condition_leakage_fail():
 
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
-                               details='Found 20.00% of index leakage',
-                               name='Ratio of leaking indices is not greater than 19.00%')
+                               details='Found 20% of index leakage',
+                               name='Ratio of leaking indices is not greater than 19%')
     ))
 
 
diff --git a/tests/checks/methodology/train_test_samples_mix_test.py b/tests/checks/methodology/train_test_samples_mix_test.py
--- a/tests/checks/methodology/train_test_samples_mix_test.py
+++ b/tests/checks/methodology/train_test_samples_mix_test.py
@@ -110,9 +110,9 @@ def test_condition_ratio_not_greater_than_not_passed(iris_clean):
     assert_that(result, has_items(
         equal_condition_result(is_pass=False,
                                name='Percentage of test data samples that appear in train data '
-                                    'not greater than 9.00%',
+                                    'not greater than 9%',
                                details='Percent of test data samples that appear in train data: '
-                                       '10.00%')
+                                       '10%')
     ))
 
 
@@ -127,5 +127,5 @@ def test_condition_ratio_not_greater_than_passed(diabetes_split_dataset_and_mode
     assert_that(result, has_items(
         equal_condition_result(is_pass=True,
                                name='Percentage of test data samples that appear in train data '
-                                    'not greater than 10.00%')
+                                    'not greater than 10%')
     ))
\ No newline at end of file
diff --git a/tests/checks/performance/model_error_analysis_test.py b/tests/checks/performance/model_error_analysis_test.py
--- a/tests/checks/performance/model_error_analysis_test.py
+++ b/tests/checks/performance/model_error_analysis_test.py
@@ -75,7 +75,7 @@ def test_condition_fail(iris_labeled_dataset, iris_adaboost):
     assert_that(condition_result, has_items(
         equal_condition_result(
             is_pass=False,
-            name='The performance difference of the detected segments must not be greater than 5.00%',
+            name='The performance difference of the detected segments must not be greater than 5%',
             details='Found change in Accuracy in features above threshold: {\'petal length (cm)\': \'10.91%\'}',
             category=ConditionCategory.WARN
         )
diff --git a/tests/checks/performance/simple_model_comparison_test.py b/tests/checks/performance/simple_model_comparison_test.py
--- a/tests/checks/performance/simple_model_comparison_test.py
+++ b/tests/checks/performance/simple_model_comparison_test.py
@@ -114,7 +114,7 @@ def test_condition_ratio_not_less_than_not_passed(diabetes_split_dataset_and_mod
     assert_that(condition_result, has_items(
         equal_condition_result(
             is_pass=False,
-            name='Model performance gain over simple model is not less than 40.00%',
+            name='Model performance gain over simple model is not less than 40%',
             details='Found metrics with gain below threshold: {\'Neg RMSE\': \'24.32%\'}')
     ))
 
@@ -129,7 +129,7 @@ def test_condition_failed_for_multiclass(iris_split_dataset_and_model):
     assert_that(result.conditions_results, has_items(
         equal_condition_result(
             is_pass=False,
-            name='Model performance gain over simple model is not less than 80.00%',
+            name='Model performance gain over simple model is not less than 80%',
             details='Found metrics with gain below threshold: {\'F1\': {1: \'78.15%\'}}')
     ))
 
@@ -144,7 +144,7 @@ def test_condition_pass_for_multiclass_avg(iris_split_dataset_and_model):
     assert_that(result.conditions_results, has_items(
         equal_condition_result(
             is_pass=True,
-            name='Model performance gain over simple model is not less than 43.00%')
+            name='Model performance gain over simple model is not less than 43%')
     ))
 
 
@@ -182,7 +182,7 @@ def test_condition_ratio_not_less_than_passed(diabetes_split_dataset_and_model):
     assert_that(condition_result, has_items(
         equal_condition_result(
             is_pass=True,
-            name='Model performance gain over simple model is not less than 10.00%'
+            name='Model performance gain over simple model is not less than 10%'
         )
     ))