sdmetrics 0.28.3.dev0__tar.gz → 0.29.1.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. {sdmetrics-0.28.3.dev0/sdmetrics.egg-info → sdmetrics-0.29.1.dev0}/PKG-INFO +1 -1
  2. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/pyproject.toml +1 -1
  3. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/__init__.py +1 -1
  4. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/_utils_metadata.py +9 -0
  5. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/multi_table/metadata.json +5 -5
  6. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/single_table/metadata.json +1 -1
  7. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/data_validity.py +88 -27
  8. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/base.py +4 -2
  9. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/boundary_adherence.py +26 -5
  10. sdmetrics-0.29.1.dev0/sdmetrics/single_column/statistical/category_adherence.py +96 -0
  11. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/datetime_format_adherence.py +3 -5
  12. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/visualization.py +21 -13
  13. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0/sdmetrics.egg-info}/PKG-INFO +1 -1
  14. sdmetrics-0.28.3.dev0/sdmetrics/single_column/statistical/category_adherence.py +0 -64
  15. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/LICENSE +0 -0
  16. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/README.md +0 -0
  17. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/base.py +0 -0
  18. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/__init__.py +0 -0
  19. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/base.py +0 -0
  20. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/__init__.py +0 -0
  21. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/cardinality_boundary_adherence.py +0 -0
  22. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/contingency_similarity.py +0 -0
  23. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/correlation_similarity.py +0 -0
  24. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/inter_row_msas.py +0 -0
  25. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/kl_divergence.py +0 -0
  26. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/referential_integrity.py +0 -0
  27. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/column_pairs/statistical/statistic_msas.py +0 -0
  28. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/multi_table/sessions_real.csv +0 -0
  29. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/multi_table/sessions_synthetic.csv +0 -0
  30. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/multi_table/transactions_real.csv +0 -0
  31. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/multi_table/transactions_synthetic.csv +0 -0
  32. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/multi_table/users_real.csv +0 -0
  33. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/multi_table/users_synthetic.csv +0 -0
  34. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/single_table/student_placements_real.csv +0 -0
  35. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/single_table/student_placements_synthetic.csv +0 -0
  36. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/timeseries/metadata.json +0 -0
  37. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/timeseries/timeseries_real.csv +0 -0
  38. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos/timeseries/timeseries_synthetic.csv +0 -0
  39. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/demos.py +0 -0
  40. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/errors.py +0 -0
  41. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/goal.py +0 -0
  42. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/README.md +0 -0
  43. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/__init__.py +0 -0
  44. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/base.py +0 -0
  45. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/detection/__init__.py +0 -0
  46. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/detection/base.py +0 -0
  47. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/detection/parent_child.py +0 -0
  48. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/multi_single_table.py +0 -0
  49. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/statistical/__init__.py +0 -0
  50. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/statistical/cardinality_shape_similarity.py +0 -0
  51. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/multi_table/statistical/cardinality_statistic_similarity.py +0 -0
  52. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/__init__.py +0 -0
  53. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/base_report.py +0 -0
  54. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/base_unified_report.py +0 -0
  55. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/diagnostic_report.py +0 -0
  56. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/__init__.py +0 -0
  57. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/__init__.py +0 -0
  58. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/base.py +0 -0
  59. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/boundary.py +0 -0
  60. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/cardinality.py +0 -0
  61. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/column_pair_trends.py +0 -0
  62. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/column_shapes.py +0 -0
  63. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/coverage.py +0 -0
  64. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/data_validity.py +0 -0
  65. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/inter_table_trends.py +0 -0
  66. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/relationship_validity.py +0 -0
  67. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/structure.py +0 -0
  68. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/_properties/synthesis.py +0 -0
  69. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/base_multi_table_report.py +0 -0
  70. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/diagnostic_report.py +0 -0
  71. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/multi_table/quality_report.py +0 -0
  72. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/quality_report.py +0 -0
  73. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/__init__.py +0 -0
  74. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/__init__.py +0 -0
  75. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/base.py +0 -0
  76. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/boundary.py +0 -0
  77. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/column_pair_trends.py +0 -0
  78. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/column_shapes.py +0 -0
  79. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/coverage.py +0 -0
  80. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/structure.py +0 -0
  81. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/_properties/synthesis.py +0 -0
  82. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/diagnostic_report.py +0 -0
  83. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/plot_utils.py +0 -0
  84. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/single_table/quality_report.py +0 -0
  85. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/reports/utils.py +0 -0
  86. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/README.md +0 -0
  87. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/__init__.py +0 -0
  88. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/__init__.py +0 -0
  89. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/category_coverage.py +0 -0
  90. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/cstest.py +0 -0
  91. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/key_uniqueness.py +0 -0
  92. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/kscomplement.py +0 -0
  93. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/missing_value_similarity.py +0 -0
  94. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/range_coverage.py +0 -0
  95. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/regex_format_adherence.py +0 -0
  96. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/sequence_length_similarity.py +0 -0
  97. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/statistic_similarity.py +0 -0
  98. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_column/statistical/tv_complement.py +0 -0
  99. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/README.md +0 -0
  100. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/__init__.py +0 -0
  101. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/base.py +0 -0
  102. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/bayesian_network.py +0 -0
  103. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/data_augmentation/__init__.py +0 -0
  104. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/data_augmentation/base.py +0 -0
  105. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/data_augmentation/binary_classifier_precision_efficacy.py +0 -0
  106. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/data_augmentation/binary_classifier_recall_efficacy.py +0 -0
  107. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/data_augmentation/utils.py +0 -0
  108. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/detection/__init__.py +0 -0
  109. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/detection/base.py +0 -0
  110. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/detection/sklearn.py +0 -0
  111. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/efficacy/__init__.py +0 -0
  112. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/efficacy/base.py +0 -0
  113. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/efficacy/binary.py +0 -0
  114. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/efficacy/mlefficacy.py +0 -0
  115. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/efficacy/multiclass.py +0 -0
  116. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/efficacy/regression.py +0 -0
  117. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/equalized_odds.py +0 -0
  118. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/gaussian_mixture.py +0 -0
  119. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/multi_column_pairs.py +0 -0
  120. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/multi_single_column.py +0 -0
  121. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/new_row_synthesis.py +0 -0
  122. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/__init__.py +0 -0
  123. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/base.py +0 -0
  124. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/cap.py +0 -0
  125. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/categorical_sklearn.py +0 -0
  126. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/dcr_baseline_protection.py +0 -0
  127. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/dcr_overfitting_protection.py +0 -0
  128. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/dcr_utils.py +0 -0
  129. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/disclosure_protection.py +0 -0
  130. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/ensemble.py +0 -0
  131. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/loss.py +0 -0
  132. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/numerical_sklearn.py +0 -0
  133. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/radius_nearest_neighbor.py +0 -0
  134. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/privacy/util.py +0 -0
  135. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/table_structure.py +0 -0
  136. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/single_table/utils.py +0 -0
  137. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/README.md +0 -0
  138. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/__init__.py +0 -0
  139. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/base.py +0 -0
  140. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/detection.py +0 -0
  141. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/efficacy/__init__.py +0 -0
  142. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/efficacy/base.py +0 -0
  143. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/efficacy/classification.py +0 -0
  144. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/timeseries/ml_scorers.py +0 -0
  145. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/utils.py +0 -0
  146. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics/warnings.py +0 -0
  147. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics.egg-info/SOURCES.txt +0 -0
  148. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics.egg-info/dependency_links.txt +0 -0
  149. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics.egg-info/entry_points.txt +0 -0
  150. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics.egg-info/requires.txt +0 -0
  151. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/sdmetrics.egg-info/top_level.txt +0 -0
  152. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/setup.cfg +0 -0
  153. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/tests/test_scripts.py +0 -0
  154. {sdmetrics-0.28.3.dev0 → sdmetrics-0.29.1.dev0}/tests/test_tasks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdmetrics
3
- Version: 0.28.3.dev0
3
+ Version: 0.29.1.dev0
4
4
  Summary: Metrics for Synthetic Data Generation Projects
5
5
  Author-email: MIT Data To AI Lab <dailabmit@gmail.com>
6
6
  License-Expression: MIT
@@ -148,7 +148,7 @@ convention = 'google'
148
148
  add-ignore = ['D107', 'D407', 'D417']
149
149
 
150
150
  [tool.bumpversion]
151
- current_version = "0.28.3.dev0"
151
+ current_version = "0.29.1.dev0"
152
152
  parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<candidate>\d+))?'
153
153
  serialize = [
154
154
  '{major}.{minor}.{patch}.{release}{candidate}',
@@ -4,7 +4,7 @@
4
4
 
5
5
  __author__ = 'MIT Data To AI Lab'
6
6
  __email__ = 'dailabmit@gmail.com'
7
- __version__ = '0.28.3.dev0'
7
+ __version__ = '0.29.1.dev0'
8
8
 
9
9
  import sys
10
10
  import warnings as python_warnings
@@ -100,6 +100,15 @@ def handle_single_and_multi_table(single_table_func):
100
100
  return wrapper
101
101
 
102
102
 
103
+ def _convert_column_to_string(column_data, column_metadata):
104
+ if is_datetime(column_data):
105
+ datetime_format = column_metadata.get('datetime_format')
106
+ if datetime_format is not None:
107
+ return column_data.dt.strftime(datetime_format)
108
+
109
+ return column_data.astype(str)
110
+
111
+
103
112
  def _convert_datetime_column(column_name, column_data, column_metadata):
104
113
  if is_datetime(column_data):
105
114
  return column_data
@@ -5,7 +5,7 @@
5
5
  "columns": {
6
6
  "user_id": {
7
7
  "sdtype": "id",
8
- "regex_format": "\\d{30}"
8
+ "regex_format": "\\d{1,30}"
9
9
  },
10
10
  "country": {
11
11
  "sdtype": "categorical"
@@ -24,11 +24,11 @@
24
24
  "columns": {
25
25
  "session_id": {
26
26
  "sdtype": "id",
27
- "regex_format": "\\d{30}"
27
+ "regex_format": "\\d{1,30}"
28
28
  },
29
29
  "user_id": {
30
30
  "sdtype": "id",
31
- "regex_format": "\\d{30}"
31
+ "regex_format": "\\d{1,30}"
32
32
  },
33
33
  "device": {
34
34
  "sdtype": "categorical"
@@ -43,11 +43,11 @@
43
43
  "columns": {
44
44
  "transaction_id": {
45
45
  "sdtype": "id",
46
- "regex_format": "\\d{30}"
46
+ "regex_format": "\\d{1,30}"
47
47
  },
48
48
  "session_id": {
49
49
  "sdtype": "id",
50
- "regex_format": "\\d{30}"
50
+ "regex_format": "\\d{1,30}"
51
51
  },
52
52
  "timestamp": {
53
53
  "sdtype": "datetime",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "student_id": {
23
23
  "sdtype": "id",
24
- "regex_format": "\\d{30}"
24
+ "regex_format": "\\d{1,30}"
25
25
  },
26
26
  "high_perc": {
27
27
  "sdtype": "numerical",
@@ -2,9 +2,16 @@ import numpy as np
2
2
  import pandas as pd
3
3
  import plotly.express as px
4
4
 
5
+ from sdmetrics._utils_metadata import _convert_column_to_string
5
6
  from sdmetrics.reports.single_table._properties import BaseSingleTableProperty
6
7
  from sdmetrics.reports.utils import PlotConfig
7
- from sdmetrics.single_column import BoundaryAdherence, CategoryAdherence, KeyUniqueness
8
+ from sdmetrics.single_column import (
9
+ BoundaryAdherence,
10
+ CategoryAdherence,
11
+ DatetimeFormatAdherence,
12
+ KeyUniqueness,
13
+ RegexFormatAdherence,
14
+ )
8
15
  from sdmetrics.utils import (
9
16
  get_alternate_keys,
10
17
  get_columns_from_metadata,
@@ -21,16 +28,53 @@ class DataValidity(BaseSingleTableProperty):
21
28
  The BoundaryAdherence metric is used for numerical and datetime columns, the CategoryAdherence
22
29
  is used for categorical and boolean columns and the KeyUniqueness for primary
23
30
  and alternate keys. The other column types are ignored by this property.
31
+
32
+ If the metadata defines the valid range of a column, it is passed down to the metric,
33
+ which uses it instead of computing it from the real data.
24
34
  """
25
35
 
26
36
  _num_iteration_case = 'column'
37
+ _metric_to_arguments = {
38
+ DatetimeFormatAdherence: ('datetime_format',),
39
+ RegexFormatAdherence: ('regex_format',),
40
+ BoundaryAdherence: ('range_min', 'range_max', 'range_is_nullable'),
41
+ CategoryAdherence: ('range_values', 'range_is_nullable'),
42
+ }
27
43
  _sdtype_to_metric = {
28
- 'numerical': BoundaryAdherence,
29
- 'datetime': BoundaryAdherence,
30
- 'categorical': CategoryAdherence,
31
- 'boolean': CategoryAdherence,
44
+ 'numerical': [BoundaryAdherence],
45
+ 'datetime': [BoundaryAdherence, DatetimeFormatAdherence],
46
+ 'categorical': [CategoryAdherence],
47
+ 'boolean': [CategoryAdherence],
48
+ 'id': [KeyUniqueness, RegexFormatAdherence],
32
49
  }
33
50
 
51
+ @classmethod
52
+ def _get_metric_arguments(cls, metric, column_name, columns_meta):
53
+ """Get the information of a column defined in the metadata.
54
+
55
+ Args:
56
+ metric (SingleColumnMetric):
57
+ The metric to compute the column score with.
58
+ column_name (str):
59
+ The name of the column.
60
+ columns_meta (dict):
61
+ The metadata of every column of the table.
62
+
63
+ Returns:
64
+ dict:
65
+ The arguments to pass down to the metric. Any information that is not
66
+ defined in the metadata is omitted.
67
+ """
68
+ arguments = cls._metric_to_arguments.get(metric)
69
+ if not arguments:
70
+ return {}
71
+
72
+ column_meta = columns_meta[column_name]
73
+ column_arguments = {
74
+ argument: column_meta[argument] for argument in arguments if argument in column_meta
75
+ }
76
+ return column_arguments
77
+
34
78
  def _generate_details(self, real_data, synthetic_data, metadata, progress_bar=None):
35
79
  """Generate the _details dataframe for the data validity property.
36
80
 
@@ -66,28 +110,45 @@ class DataValidity(BaseSingleTableProperty):
66
110
  is_unique = primary_key_match or alternate_key_match
67
111
  is_sequence_index = column_name == sequence_index
68
112
 
69
- try:
70
- if sdtype not in self._sdtype_to_metric and not is_unique:
71
- continue
72
-
73
- if is_sequence_index and self._sdtype_to_metric.get(sdtype) == BoundaryAdherence:
74
- continue
75
-
76
- metric = self._sdtype_to_metric.get(sdtype, KeyUniqueness)
77
- column_score = metric.compute(real_data[column_name], synthetic_data[column_name])
78
- error_message = None
79
-
80
- except Exception as e:
81
- column_score = np.nan
82
- error_message = f'{type(e).__name__}: {e}'
83
- finally:
84
- if progress_bar:
85
- progress_bar.update()
86
-
87
- column_names.append(column_name)
88
- metric_names.append(metric.__name__)
89
- scores.append(column_score)
90
- error_messages.append(error_message)
113
+ if (sdtype == 'id' or sdtype not in self._sdtype_to_metric) and not is_unique:
114
+ continue
115
+
116
+ if is_sequence_index and BoundaryAdherence in self._sdtype_to_metric.get(sdtype):
117
+ continue
118
+
119
+ metrics = self._sdtype_to_metric.get(sdtype, [KeyUniqueness])
120
+ for metric in metrics:
121
+ try:
122
+ metric_arguments = self._get_metric_arguments(metric, column_name, columns_meta)
123
+ if metric in [DatetimeFormatAdherence, RegexFormatAdherence]:
124
+ column_meta = columns_meta[column_name]
125
+ real_column = _convert_column_to_string(real_data[column_name], column_meta)
126
+ synthetic_column = _convert_column_to_string(
127
+ synthetic_data[column_name], column_meta
128
+ )
129
+ column_score = metric.compute(
130
+ real_column, synthetic_column, **metric_arguments
131
+ )
132
+ else:
133
+ column_score = metric.compute(
134
+ real_data[column_name],
135
+ synthetic_data[column_name],
136
+ **metric_arguments,
137
+ )
138
+
139
+ error_message = None
140
+
141
+ except Exception as e:
142
+ column_score = np.nan
143
+ error_message = f'{type(e).__name__}: {e}'
144
+ finally:
145
+ if progress_bar:
146
+ progress_bar.update()
147
+
148
+ column_names.append(column_name)
149
+ metric_names.append(metric.__name__)
150
+ scores.append(column_score)
151
+ error_messages.append(error_message)
91
152
 
92
153
  result = pd.DataFrame({
93
154
  'Column': column_names,
@@ -41,7 +41,7 @@ class SingleColumnMetric(BaseMetric):
41
41
  raise NotImplementedError()
42
42
 
43
43
  @classmethod
44
- def compute_breakdown(cls, real_data, synthetic_data):
44
+ def compute_breakdown(cls, real_data, synthetic_data, **kwargs):
45
45
  """Compute this metric breakdown.
46
46
 
47
47
  Args:
@@ -51,9 +51,11 @@ class SingleColumnMetric(BaseMetric):
51
51
  synthetic_data (Union[numpy.ndarray, pandas.Series]):
52
52
  The values from the synthetic dataset, passed as a 1d numpy
53
53
  array or as a pandas.Series.
54
+ **kwargs:
55
+ Additional keyword arguments to pass to the ``compute`` method.
54
56
 
55
57
  Returns:
56
58
  dict
57
59
  Mapping of the metric output. Must include the key 'score'.
58
60
  """
59
- return {'score': cls.compute(real_data, synthetic_data)}
61
+ return {'score': cls.compute(real_data, synthetic_data, **kwargs)}
@@ -11,7 +11,8 @@ class BoundaryAdherence(SingleColumnMetric):
11
11
  """Boundary adherence metric.
12
12
 
13
13
  Compute the fraction of rows in the synthetic data that are within the min and max
14
- bounds of the real data
14
+ bounds of the real data. If any of ``range_min``, ``range_max`` or ``range_is_nullable``
15
+ are provided, they are used instead of the values computed from the real data.
15
16
 
16
17
  Attributes:
17
18
  name (str):
@@ -30,7 +31,9 @@ class BoundaryAdherence(SingleColumnMetric):
30
31
  max_value = 1.0
31
32
 
32
33
  @classmethod
33
- def compute(cls, real_data, synthetic_data):
34
+ def compute(
35
+ cls, real_data, synthetic_data, range_min=None, range_max=None, range_is_nullable=None
36
+ ):
34
37
  """Compute the boundary adherence of two continuous columns.
35
38
 
36
39
  Args:
@@ -38,6 +41,15 @@ class BoundaryAdherence(SingleColumnMetric):
38
41
  The values from the real dataset.
39
42
  synthetic_data (Union[numpy.ndarray, pandas.Series]):
40
43
  The values from the synthetic dataset.
44
+ range_min (float or datetime, optional):
45
+ The minimum value the column is allowed to take. If ``None``, the minimum
46
+ value of the real data is used instead. Defaults to ``None``.
47
+ range_max (float or datetime, optional):
48
+ The maximum value the column is allowed to take. If ``None``, the maximum
49
+ value of the real data is used instead. Defaults to ``None``.
50
+ range_is_nullable (bool, optional):
51
+ Whether the column is allowed to contain missing values.
52
+ Defaults to ``None``.
41
53
 
42
54
  Returns:
43
55
  float:
@@ -45,15 +57,24 @@ class BoundaryAdherence(SingleColumnMetric):
45
57
  """
46
58
  real_data = pd.Series(real_data)
47
59
  synthetic_data = pd.Series(synthetic_data)
48
- if any(pd.isna(real_data)):
49
- real_data = real_data.dropna()
60
+
61
+ range_min = real_data.min() if range_min is None else range_min
62
+ range_max = real_data.max() if range_max is None else range_max
63
+
64
+ if range_is_nullable is None:
65
+ range_is_nullable = any(pd.isna(real_data))
66
+
67
+ real_data = real_data.dropna()
68
+ if range_is_nullable:
50
69
  synthetic_data = synthetic_data.dropna()
51
70
 
52
71
  if is_datetime(real_data):
72
+ bounds = pd.to_datetime([range_min, range_max]).astype(real_data.dtype)
53
73
  real_data = pd.to_numeric(real_data)
54
74
  synthetic_data = pd.to_numeric(synthetic_data)
75
+ range_min, range_max = pd.to_numeric(bounds)
55
76
 
56
- valid = synthetic_data.between(real_data.min(), real_data.max())
77
+ valid = synthetic_data.between(range_min, range_max)
57
78
 
58
79
  return valid.sum() / len(synthetic_data)
59
80
 
@@ -0,0 +1,96 @@
1
+ """Category Adherence Metric."""
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+
6
+ from sdmetrics.goal import Goal
7
+ from sdmetrics.single_column.base import SingleColumnMetric
8
+
9
+
10
+ class CategoryAdherence(SingleColumnMetric):
11
+ """Category adherence metric.
12
+
13
+ The proportion of synthetic data points that match an existing category from the real data.
14
+ If any of ``range_values`` or ``range_is_nullable`` are provided, they are used instead of
15
+ the categories computed from the real data.
16
+
17
+ Attributes:
18
+ name (str):
19
+ Name to use when reports about this metric are printed.
20
+ goal (sdmetrics.goal.Goal):
21
+ The goal of this metric.
22
+ min_value (Union[float, tuple[float]]):
23
+ Minimum value or values that this metric can take.
24
+ max_value (Union[float, tuple[float]]):
25
+ Maximum value or values that this metric can take.
26
+ """
27
+
28
+ name = 'CategoryAdherence'
29
+ goal = Goal.MAXIMIZE
30
+ min_value = 0.0
31
+ max_value = 1.0
32
+
33
+ @classmethod
34
+ def compute_breakdown(
35
+ cls, real_data, synthetic_data, range_values=None, range_is_nullable=None
36
+ ):
37
+ """Compute the score breakdown of the category adherence metric.
38
+
39
+ Args:
40
+ real_data (pandas.Series):
41
+ The real data.
42
+ synthetic_data (pandas.Series):
43
+ The synthetic data.
44
+ range_values (List[str], optional):
45
+ The list of categories the column is allowed to take. If ``None``, the
46
+ categories of the real data are used instead. Defaults to ``None``.
47
+ range_is_nullable (bool, optional):
48
+ Whether the column is allowed to contain missing values.
49
+ Defaults to ``None``.
50
+
51
+ Returns:
52
+ dict:
53
+ The score breakdown of the category adherence metric.
54
+ """
55
+ real_data = real_data.fillna(np.nan)
56
+ synthetic_data = synthetic_data.fillna(np.nan)
57
+ if range_values is None:
58
+ valid_values = pd.Series(real_data.unique())
59
+ else:
60
+ valid_values = pd.Series(list(range_values))
61
+
62
+ if range_is_nullable is None:
63
+ range_is_nullable = any(pd.isna(real_data)) or any(pd.isna(valid_values))
64
+
65
+ valid = synthetic_data.isin(valid_values.dropna())
66
+ if range_is_nullable:
67
+ valid = valid | pd.isna(synthetic_data)
68
+
69
+ return {'score': valid.mean()}
70
+
71
+ @classmethod
72
+ def compute(cls, real_data, synthetic_data, range_values=None, range_is_nullable=None):
73
+ """Compute the category adherence of two columns.
74
+
75
+ Args:
76
+ real_data (pandas.Series):
77
+ The real data.
78
+ synthetic_data (pandas.Series):
79
+ The synthetic data.
80
+ range_values (List[str], optional):
81
+ The list of categories the column is allowed to take. If ``None``, the
82
+ categories of the real data are used instead. Defaults to ``None``.
83
+ range_is_nullable (bool, optional):
84
+ Whether the column is allowed to contain missing values.
85
+ Defaults to ``None``.
86
+
87
+ Returns:
88
+ float:
89
+ The category adherence metric score.
90
+ """
91
+ return cls.compute_breakdown(
92
+ real_data,
93
+ synthetic_data,
94
+ range_values=range_values,
95
+ range_is_nullable=range_is_nullable,
96
+ )['score']
@@ -6,10 +6,10 @@ from datetime import datetime
6
6
 
7
7
  import numpy as np
8
8
  import pandas as pd
9
- from pandas.api.types import is_string_dtype
10
9
 
11
10
  from sdmetrics.goal import Goal
12
11
  from sdmetrics.single_column.base import SingleColumnMetric
12
+ from sdmetrics.utils import is_datetime
13
13
 
14
14
 
15
15
  class DatetimeFormatAdherence(SingleColumnMetric):
@@ -92,13 +92,11 @@ class DatetimeFormatAdherence(SingleColumnMetric):
92
92
  float:
93
93
  The proportion of data points in the synthetic data that match the datetime format.
94
94
  """
95
- real_data_nan = pd.isna(real_data)
96
- synthetic_data_nan = pd.isna(synthetic_data)
97
- if not is_string_dtype(synthetic_data[~synthetic_data_nan]):
95
+ if is_datetime(synthetic_data):
98
96
  return np.nan
99
97
 
100
98
  cls._validate_datetime_format(datetime_format)
101
- if is_string_dtype(real_data[~real_data_nan]):
99
+ if not is_datetime(real_data):
102
100
  real_valid_rows = cls._filter_valid_datetime_rows(real_data, datetime_format)
103
101
  if len(real_valid_rows) != len(real_data):
104
102
  invalid = real_data[~real_data.index.isin(real_valid_rows.index)]
@@ -5,9 +5,9 @@ from functools import wraps
5
5
 
6
6
  import pandas as pd
7
7
  import plotly.express as px
8
- import plotly.figure_factory as ff
9
8
  import plotly.graph_objects as go
10
9
  import plotly.io as pio
10
+ import scipy
11
11
  from pandas.api.types import is_datetime64_dtype
12
12
 
13
13
  from sdmetrics.reports.utils import PlotConfig
@@ -252,22 +252,30 @@ def _generate_column_distplot(real_data, synthetic_data, plot_kwargs={}):
252
252
  col_names.append('Synthetic')
253
253
  colors.append(PlotConfig.DATACEBO_GREEN)
254
254
 
255
- default_distplot_kwargs = {
256
- 'show_hist': False,
257
- 'show_rug': False,
258
- 'colors': colors,
259
- }
260
-
261
255
  has_data = any(len(data) > 0 for data in hist_data)
262
256
 
263
- if has_data:
264
- return ff.create_distplot(
265
- hist_data,
266
- col_names,
267
- **{**default_distplot_kwargs, **plot_kwargs},
257
+ if not has_data:
258
+ return go.Figure()
259
+
260
+ traces = []
261
+ for index, data in enumerate(hist_data):
262
+ start = min(data)
263
+ end = max(data)
264
+
265
+ curve_x = [start + x * (end - start) / 500 for x in range(500)]
266
+ curve_y = scipy.stats.gaussian_kde(data)(curve_x)
267
+
268
+ traces.append(
269
+ go.Scatter(
270
+ x=curve_x,
271
+ y=curve_y,
272
+ mode='lines',
273
+ name=col_names[index],
274
+ line={'color': colors[index]},
275
+ )
268
276
  )
269
277
 
270
- return go.Figure()
278
+ return go.Figure(data=traces, **plot_kwargs)
271
279
 
272
280
 
273
281
  def _generate_column_plot(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdmetrics
3
- Version: 0.28.3.dev0
3
+ Version: 0.29.1.dev0
4
4
  Summary: Metrics for Synthetic Data Generation Projects
5
5
  Author-email: MIT Data To AI Lab <dailabmit@gmail.com>
6
6
  License-Expression: MIT
@@ -1,64 +0,0 @@
1
- """Category Adherence Metric."""
2
-
3
- import numpy as np
4
-
5
- from sdmetrics.goal import Goal
6
- from sdmetrics.single_column.base import SingleColumnMetric
7
-
8
-
9
- class CategoryAdherence(SingleColumnMetric):
10
- """Category adherence metric.
11
-
12
- The proportion of synthetic data points that match an existing category from the real data.
13
-
14
- Attributes:
15
- name (str):
16
- Name to use when reports about this metric are printed.
17
- goal (sdmetrics.goal.Goal):
18
- The goal of this metric.
19
- min_value (Union[float, tuple[float]]):
20
- Minimum value or values that this metric can take.
21
- max_value (Union[float, tuple[float]]):
22
- Maximum value or values that this metric can take.
23
- """
24
-
25
- name = 'CategoryAdherence'
26
- goal = Goal.MAXIMIZE
27
- min_value = 0.0
28
- max_value = 1.0
29
-
30
- @classmethod
31
- def compute_breakdown(cls, real_data, synthetic_data):
32
- """Compute the score breakdown of the category adherence metric.
33
-
34
- Args:
35
- real_data (pandas.Series):
36
- The real data.
37
- synthetic_data (pandas.Series):
38
- The synthetic data.
39
-
40
- Returns:
41
- dict:
42
- The score breakdown of the category adherence metric.
43
- """
44
- real_data = real_data.fillna(np.nan)
45
- synthetic_data = synthetic_data.fillna(np.nan)
46
- score = synthetic_data.isin(real_data).mean()
47
-
48
- return {'score': score}
49
-
50
- @classmethod
51
- def compute(cls, real_data, synthetic_data):
52
- """Compute the category adherence of two columns.
53
-
54
- Args:
55
- real_data (pandas.Series):
56
- The real data.
57
- synthetic_data (pandas.Series):
58
- The synthetic data.
59
-
60
- Returns:
61
- float:
62
- The category adherence metric score.
63
- """
64
- return cls.compute_breakdown(real_data, synthetic_data)['score']
File without changes