sdv 2.0.0.dev0__tar.gz → 2.0.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 (79) hide show
  1. {sdv-2.0.0.dev0/sdv.egg-info → sdv-2.0.1.dev0}/PKG-INFO +6 -7
  2. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/pyproject.toml +5 -7
  3. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/__init__.py +1 -1
  4. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/base.py +7 -0
  5. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/programmable_constraint.py +4 -0
  6. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/base.py +112 -34
  7. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sequential/par.py +15 -7
  8. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/base.py +38 -18
  9. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0/sdv.egg-info}/PKG-INFO +6 -7
  10. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/requires.txt +7 -8
  11. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/LICENSE +0 -0
  12. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/README.md +0 -0
  13. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/_utils.py +0 -0
  14. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/__init__.py +0 -0
  15. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/_errors.py +0 -0
  16. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/_utils.py +0 -0
  17. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/fixed_combinations.py +0 -0
  18. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/fixed_increments.py +0 -0
  19. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/inequality.py +0 -0
  20. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/one_hot_encoding.py +0 -0
  21. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/range.py +0 -0
  22. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/__init__.py +0 -0
  23. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/data_processor.py +0 -0
  24. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/datetime_formatter.py +0 -0
  25. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/errors.py +0 -0
  26. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/numerical_formatter.py +0 -0
  27. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/utils.py +0 -0
  28. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/__init__.py +0 -0
  29. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/_utils.py +0 -0
  30. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/demo.py +0 -0
  31. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/local.py +0 -0
  32. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/errors.py +0 -0
  33. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/__init__.py +0 -0
  34. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/_visualization.py +0 -0
  35. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/evaluation.py +0 -0
  36. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/utils.py +0 -0
  37. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/io/__init__.py +0 -0
  38. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/io/local/__init__.py +0 -0
  39. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/io/local/local.py +0 -0
  40. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/__init__.py +0 -0
  41. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/logger.py +0 -0
  42. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/sdv_logger_config.yml +0 -0
  43. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/utils.py +0 -0
  44. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/__init__.py +0 -0
  45. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/_single_table.py +0 -0
  46. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/errors.py +0 -0
  47. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/metadata.py +0 -0
  48. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/metadata_upgrader.py +0 -0
  49. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/utils.py +0 -0
  50. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/visualization.py +0 -0
  51. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/__init__.py +0 -0
  52. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/demos.py +0 -0
  53. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/relational.py +0 -0
  54. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/tabular.py +0 -0
  55. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/timeseries.py +0 -0
  56. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/__init__.py +0 -0
  57. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/dayz.py +0 -0
  58. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/hma.py +0 -0
  59. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/utils.py +0 -0
  60. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/__init__.py +0 -0
  61. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/hierarchical_sampler.py +0 -0
  62. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/independent_sampler.py +0 -0
  63. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/tabular.py +0 -0
  64. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sequential/__init__.py +0 -0
  65. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/__init__.py +0 -0
  66. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/copulagan.py +0 -0
  67. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/copulas.py +0 -0
  68. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/ctgan.py +0 -0
  69. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/dayz.py +0 -0
  70. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/mixins.py +0 -0
  71. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/utils.py +0 -0
  72. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/utils/__init__.py +0 -0
  73. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/utils/utils.py +0 -0
  74. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/version/__init__.py +0 -0
  75. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/SOURCES.txt +0 -0
  76. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/dependency_links.txt +0 -0
  77. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/entry_points.txt +0 -0
  78. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/top_level.txt +0 -0
  79. {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdv
3
- Version: 2.0.0.dev0
3
+ Version: 2.0.1.dev0
4
4
  Summary: Generate synthetic data for single table, multi table and sequential data
5
5
  Author-email: "DataCebo, Inc." <info@sdv.dev>
6
6
  License-Expression: BUSL-1.1
@@ -14,14 +14,13 @@ Classifier: Development Status :: 5 - Production/Stable
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: Natural Language :: English
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.9
18
17
  Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
21
20
  Classifier: Programming Language :: Python :: 3.13
22
21
  Classifier: Programming Language :: Python :: 3.14
23
22
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
- Requires-Python: <3.15,>=3.9
23
+ Requires-Python: <3.15,>=3.10
25
24
  Description-Content-Type: text/markdown
26
25
  License-File: LICENSE
27
26
  Requires-Dist: boto3<2.0.0,>=1.28
@@ -29,8 +28,7 @@ Requires-Dist: botocore<2.0.0,>=1.31
29
28
  Requires-Dist: cloudpickle>=2.1.0; python_version < "3.14"
30
29
  Requires-Dist: cloudpickle>=3.1.1; python_version >= "3.14"
31
30
  Requires-Dist: graphviz>=0.13.2
32
- Requires-Dist: numpy>=1.22.2; python_version < "3.10"
33
- Requires-Dist: numpy>=1.24.0; python_version >= "3.10" and python_version < "3.12"
31
+ Requires-Dist: numpy>=1.24.0; python_version < "3.12"
34
32
  Requires-Dist: numpy>=1.26.0; python_version >= "3.12" and python_version < "3.13"
35
33
  Requires-Dist: numpy>=2.1.0; python_version >= "3.13" and python_version < "3.14"
36
34
  Requires-Dist: numpy>=2.3.2; python_version >= "3.14"
@@ -46,7 +44,7 @@ Requires-Dist: ctgan>=0.11.1; python_version < "3.14"
46
44
  Requires-Dist: ctgan>=0.12.0; python_version >= "3.14"
47
45
  Requires-Dist: deepecho>=0.7.0; python_version < "3.14"
48
46
  Requires-Dist: deepecho>=0.8.0; python_version >= "3.14"
49
- Requires-Dist: rdt>=2.0.0.dev0
47
+ Requires-Dist: rdt>=2.0.0
50
48
  Requires-Dist: sdmetrics>=0.32.0
51
49
  Requires-Dist: platformdirs>=4.0
52
50
  Requires-Dist: pyyaml>=6.0.1
@@ -64,7 +62,6 @@ Requires-Dist: google-api-python-client; extra == "test"
64
62
  Requires-Dist: google-auth; extra == "test"
65
63
  Requires-Dist: google-auth-oauthlib; extra == "test"
66
64
  Requires-Dist: requests; extra == "test"
67
- Requires-Dist: pyarrow; extra == "test"
68
65
  Requires-Dist: gitpython; extra == "test"
69
66
  Requires-Dist: slack-sdk<4.0,>=3.23; extra == "test"
70
67
  Provides-Extra: pomegranate
@@ -91,6 +88,8 @@ Requires-Dist: coverage<8,>=4.5.12; extra == "dev"
91
88
  Requires-Dist: invoke; extra == "dev"
92
89
  Provides-Extra: readme
93
90
  Requires-Dist: rundoc<0.5,>=0.4.3; extra == "readme"
91
+ Provides-Extra: benchmark
92
+ Requires-Dist: pyarrow; extra == "benchmark"
94
93
  Dynamic: license-file
95
94
 
96
95
  <div align="center">
@@ -7,7 +7,6 @@ classifiers = [
7
7
  'Intended Audience :: Developers',
8
8
  'Natural Language :: English',
9
9
  'Programming Language :: Python :: 3',
10
- 'Programming Language :: Python :: 3.9',
11
10
  'Programming Language :: Python :: 3.10',
12
11
  'Programming Language :: Python :: 3.11',
13
12
  'Programming Language :: Python :: 3.12',
@@ -19,7 +18,7 @@ keywords = ['sdv', 'synthetic-data', 'synthetic-data-generation', 'timeseries',
19
18
  dynamic = ['version']
20
19
  license = 'BUSL-1.1'
21
20
  license-files = ['LICENSE']
22
- requires-python = '>=3.9,<3.15'
21
+ requires-python = '>=3.10,<3.15'
23
22
  readme = 'README.md'
24
23
  dependencies = [
25
24
  'boto3>=1.28,<2.0.0',
@@ -27,8 +26,7 @@ dependencies = [
27
26
  "cloudpickle>=2.1.0;python_version<'3.14'",
28
27
  "cloudpickle>=3.1.1;python_version>='3.14'",
29
28
  'graphviz>=0.13.2',
30
- "numpy>=1.22.2;python_version<'3.10'",
31
- "numpy>=1.24.0;python_version>='3.10' and python_version<'3.12'",
29
+ "numpy>=1.24.0;python_version<'3.12'",
32
30
  "numpy>=1.26.0;python_version>='3.12' and python_version<'3.13'",
33
31
  "numpy>=2.1.0;python_version>='3.13' and python_version<'3.14'",
34
32
  "numpy>=2.3.2;python_version>='3.14'",
@@ -44,7 +42,7 @@ dependencies = [
44
42
  "ctgan>=0.12.0;python_version>='3.14'",
45
43
  "deepecho>=0.7.0;python_version<'3.14'",
46
44
  "deepecho>=0.8.0;python_version>='3.14'",
47
- "rdt>=2.0.0.dev0",
45
+ "rdt>=2.0.0",
48
46
  "sdmetrics>=0.32.0",
49
47
  'platformdirs>=4.0',
50
48
  'pyyaml>=6.0.1',
@@ -74,7 +72,6 @@ test = [
74
72
  'google-auth',
75
73
  'google-auth-oauthlib',
76
74
  'requests',
77
- 'pyarrow',
78
75
  'gitpython',
79
76
  'slack-sdk>=3.23,<4.0',
80
77
  ]
@@ -113,6 +110,7 @@ dev = [
113
110
  'invoke'
114
111
  ]
115
112
  readme = ['rundoc>=0.4.3,<0.5',]
113
+ benchmark = ['pyarrow']
116
114
 
117
115
  [tool.setuptools]
118
116
  include-package-data = true
@@ -148,7 +146,7 @@ namespaces = false
148
146
  version = {attr = 'sdv.__version__'}
149
147
 
150
148
  [tool.bumpversion]
151
- current_version = "2.0.0.dev0"
149
+ current_version = "2.0.1.dev0"
152
150
  parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<candidate>\d+))?'
153
151
  serialize = [
154
152
  '{major}.{minor}.{patch}.{release}{candidate}',
@@ -6,7 +6,7 @@
6
6
 
7
7
  __author__ = 'DataCebo, Inc.'
8
8
  __email__ = 'info@sdv.dev'
9
- __version__ = '2.0.0.dev0'
9
+ __version__ = '2.0.1.dev0'
10
10
 
11
11
 
12
12
  import sys
@@ -90,8 +90,15 @@ class BaseConstraint:
90
90
  f'{missing_attrs} are not saved as attributes on the constraint.'
91
91
  )
92
92
 
93
+ if self._is_single_table and getattr(self, '_table_name', None) is not None:
94
+ instanced['table_name'] = self._table_name
95
+
93
96
  return {'class_name': self.__class__.__name__, 'parameters': instanced}
94
97
 
98
+ def to_dict(self):
99
+ """Return the constraint as a serializable dictionary."""
100
+ return self.get_constraint_dict()
101
+
95
102
  @classmethod
96
103
  def load_constraint_from_dict(cls, parameters):
97
104
  """Uses the given parameters to recreate an instance of the constraint."""
@@ -41,6 +41,10 @@ class ProgrammableConstraint:
41
41
  'parameters': instanced,
42
42
  }
43
43
 
44
+ def to_dict(self):
45
+ """Return the constraint as a serializable dictionary."""
46
+ return self.get_constraint_dict()
47
+
44
48
  @classmethod
45
49
  def load_constraint_from_dict(cls, parameters):
46
50
  """Uses the given parameters to recreate an instance of the constraint."""
@@ -574,7 +574,7 @@ class BaseMultiTableSynthesizer:
574
574
  If ``table_name`` is not present in the metadata.
575
575
  """
576
576
  self._validate_table_name(table_name)
577
- return self._table_synthesizers[table_name].get_transformers()
577
+ return self._table_synthesizers[table_name].get_transformers(table_name=table_name)
578
578
 
579
579
  def update_transformers(self, table_name, column_name_to_transformer):
580
580
  """Update any of the transformers assigned to each of the column names.
@@ -590,7 +590,9 @@ class BaseMultiTableSynthesizer:
590
590
  If ``table_name`` is not present in the metadata.
591
591
  """
592
592
  self._validate_table_name(table_name)
593
- self._table_synthesizers[table_name].update_transformers(column_name_to_transformer)
593
+ self._table_synthesizers[table_name].update_transformers(
594
+ column_name_to_transformer, table_name=table_name
595
+ )
594
596
 
595
597
  def _store_and_convert_original_cols(self, data):
596
598
  list_of_changed_tables = []
@@ -756,8 +758,8 @@ class BaseMultiTableSynthesizer:
756
758
 
757
759
  def _validate_sample_input(
758
760
  self,
759
- table_name,
760
761
  num_rows,
762
+ main_table_name,
761
763
  batch_size,
762
764
  max_tries_per_batch,
763
765
  output_folder_path,
@@ -769,9 +771,17 @@ class BaseMultiTableSynthesizer:
769
771
  'sampling synthetic data.'
770
772
  )
771
773
 
774
+ if main_table_name is None:
775
+ raise SynthesizerInputError(
776
+ '`main_table_name` cannot be None for multi-table sampling. '
777
+ 'Please provide a table name.'
778
+ )
779
+
772
780
  table_names = list(self.get_metadata().tables)
773
- if table_name not in table_names:
774
- raise SynthesizerInputError(f"Table '{table_name}' does not exist in the metadata.")
781
+ if main_table_name not in table_names:
782
+ raise SynthesizerInputError(
783
+ f"Table '{main_table_name}' does not exist in the metadata."
784
+ )
775
785
 
776
786
  _validate_positive_integer('num_rows', num_rows)
777
787
  _validate_positive_integer('max_tries_per_batch', max_tries_per_batch)
@@ -818,35 +828,7 @@ class BaseMultiTableSynthesizer:
818
828
 
819
829
  return pd.concat(sampled, ignore_index=True)
820
830
 
821
- def sample(
822
- self,
823
- table_name,
824
- num_rows,
825
- batch_size=None,
826
- max_tries_per_batch=100,
827
- output_folder_path=None,
828
- ):
829
- """Generate synthetic data for the entire dataset.
830
-
831
- Args:
832
- table_name (str):
833
- The name of the main table to sample.
834
- num_rows (int):
835
- The number of rows to sample.
836
- batch_size (int, optional):
837
- The batch size for sampling. Defaults to None.
838
- max_tries_per_batch (int, optional):
839
- The maximum number of tries per batch. Defaults to 100.
840
- output_folder_path (str, optional):
841
- The folder path to save the sampled data. Defaults to None.
842
-
843
- Returns:
844
- dict: A dictionary containing the sampled data for each table.
845
- """
846
- self._validate_sample_input(
847
- table_name, num_rows, batch_size, max_tries_per_batch, output_folder_path
848
- )
849
- scale = self._resolve_scale(table_name, num_rows)
831
+ def _sample_from_scale(self, scale, batch_size, max_tries_per_batch, output_folder_path):
850
832
  with self._set_temp_numpy_seed(), disable_single_table_logger():
851
833
  sampled_data = self._sample(
852
834
  scale=scale,
@@ -878,6 +860,102 @@ class BaseMultiTableSynthesizer:
878
860
  if output_folder_path is not None:
879
861
  self._save_sampled_data(sampled_data, output_folder_path)
880
862
 
863
+ return sampled_data, total_rows, total_columns
864
+
865
+ def sample_scale(
866
+ self,
867
+ scale=1.0,
868
+ batch_size=None,
869
+ max_tries_per_batch=100,
870
+ output_folder_path=None,
871
+ ):
872
+ """Generate synthetic data for the entire dataset.
873
+
874
+ Args:
875
+ scale (float):
876
+ A float representing how much to scale the data by. If scale is set to ``1.0``,
877
+ this does not scale the sizes of the tables. If ``scale`` is greater than ``1.0``
878
+ create more rows than the original data by a factor of ``scale``.
879
+ If ``scale`` is lower than ``1.0`` create fewer rows by the factor of ``scale``
880
+ than the original tables. Defaults to ``1.0``.
881
+ batch_size (int, optional):
882
+ The batch size for sampling. Defaults to None.
883
+ max_tries_per_batch (int, optional):
884
+ The maximum number of tries per batch. Defaults to 100.
885
+ output_folder_path (str, optional):
886
+ The folder path to save the sampled data. Defaults to None.
887
+
888
+ Returns:
889
+ dict: A dictionary containing the sampled data for each table.
890
+ """
891
+ if not self._fitted:
892
+ raise SamplingError(
893
+ 'This synthesizer has not been fitted. Please fit your synthesizer first before '
894
+ 'sampling synthetic data.'
895
+ )
896
+
897
+ if type(scale) not in (float, int) or not scale > 0:
898
+ raise SynthesizerInputError(
899
+ f"Invalid parameter for 'scale' ({scale}). Please provide a number that is >0.0."
900
+ )
901
+ self._validate_sample_input(
902
+ num_rows=1,
903
+ main_table_name=list(self.metadata.tables)[0],
904
+ batch_size=batch_size,
905
+ max_tries_per_batch=max_tries_per_batch,
906
+ output_folder_path=output_folder_path,
907
+ )
908
+
909
+ sampled_data, total_rows, total_columns = self._sample_from_scale(
910
+ scale, batch_size, max_tries_per_batch, output_folder_path
911
+ )
912
+
913
+ SYNTHESIZER_LOGGER.info({
914
+ 'EVENT': 'Sample',
915
+ 'TIMESTAMP': datetime.datetime.now(),
916
+ 'SYNTHESIZER CLASS NAME': self.__class__.__name__,
917
+ 'SYNTHESIZER ID': self._synthesizer_id,
918
+ 'TOTAL NUMBER OF TABLES': len(sampled_data),
919
+ 'TOTAL NUMBER OF ROWS': total_rows,
920
+ 'TOTAL NUMBER OF COLUMNS': total_columns,
921
+ })
922
+
923
+ return sampled_data
924
+
925
+ def sample(
926
+ self,
927
+ num_rows,
928
+ main_table_name=None,
929
+ batch_size=None,
930
+ max_tries_per_batch=100,
931
+ output_folder_path=None,
932
+ ):
933
+ """Generate synthetic data for the entire dataset.
934
+
935
+ Args:
936
+ num_rows (int):
937
+ The number of rows to sample.
938
+ main_table_name (str):
939
+ The name of the main table to sample.
940
+ batch_size (int, optional):
941
+ The batch size for sampling. Defaults to None.
942
+ max_tries_per_batch (int, optional):
943
+ The maximum number of tries per batch. Defaults to 100.
944
+ output_folder_path (str, optional):
945
+ The folder path to save the sampled data. Defaults to None.
946
+
947
+ Returns:
948
+ dict: A dictionary containing the sampled data for each table.
949
+ """
950
+ self._validate_sample_input(
951
+ num_rows, main_table_name, batch_size, max_tries_per_batch, output_folder_path
952
+ )
953
+ scale = self._resolve_scale(main_table_name, num_rows)
954
+
955
+ sampled_data, total_rows, total_columns = self._sample_from_scale(
956
+ scale, batch_size, max_tries_per_batch, output_folder_path
957
+ )
958
+
881
959
  SYNTHESIZER_LOGGER.info({
882
960
  'EVENT': 'Sample',
883
961
  'TIMESTAMP': datetime.datetime.now(),
@@ -427,17 +427,25 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
427
427
 
428
428
  return processed_table_data
429
429
 
430
- def update_transformers(self, column_name_to_transformer):
430
+ def update_transformers(self, column_name_to_transformer, table_name=None):
431
431
  """Update any of the transformers assigned to each of the column names.
432
432
 
433
433
  Args:
434
434
  column_name_to_transformer (dict):
435
435
  Dict mapping column names to transformers to be used for that column.
436
+ table_name (str, optional):
437
+ The name of the table for which to update the transformers. If not provided,
438
+ will use the default table name associated with the synthesizer.
436
439
 
437
440
  Raises:
438
441
  ValueError:
439
442
  Raise when the transformer of a context column is passed.
440
443
  """
444
+ if table_name is not None:
445
+ self._validate_table_name(table_name)
446
+ else:
447
+ table_name = self._table_name
448
+
441
449
  forbidden_updates = []
442
450
  for column in set(column_name_to_transformer).intersection(set(self.context_columns)):
443
451
  if self._get_table_metadata().columns[column]['sdtype'] in MODELABLE_SDTYPES:
@@ -448,7 +456,7 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
448
456
  'Transformers for context columns are not allowed to be updated.'
449
457
  )
450
458
 
451
- super().update_transformers(column_name_to_transformer)
459
+ super().update_transformers(column_name_to_transformer, table_name=table_name)
452
460
 
453
461
  def _fit_context_model(self, processed_table_data):
454
462
  LOGGER.debug(f'Fitting context synthesizer {self._context_synthesizer.__class__.__name__}')
@@ -639,8 +647,8 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
639
647
 
640
648
  def sample(
641
649
  self,
642
- table_name,
643
650
  num_rows,
651
+ main_table_name=None,
644
652
  max_tries_per_batch=100,
645
653
  batch_size=None,
646
654
  output_folder_path=None,
@@ -651,10 +659,10 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
651
659
  ``sample_sequences`` instead.
652
660
 
653
661
  Args:
654
- table_name (str):
655
- Name of the table to sample.
656
662
  num_rows (int):
657
663
  Number of rows to sample.
664
+ main_table_name (str or None):
665
+ Name of the table to sample.
658
666
  max_tries_per_batch (int):
659
667
  Number of times to retry sampling discarded rows. Defaults to 100.
660
668
  batch_size (int or None):
@@ -725,8 +733,8 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
725
733
  condition_columns = context_columns[condition_columns].to_dict('records')
726
734
  synthesizer_conditions = [Condition(conditions) for conditions in condition_columns]
727
735
  context = self._context_synthesizer.sample_from_conditions(synthesizer_conditions)
728
- context.update(context_columns)
729
- return self._sample(context, sequence_length)
736
+ context[self._table_name].update(context_columns)
737
+ return {self._table_name: self._sample(context[self._table_name], sequence_length)}
730
738
 
731
739
  def _process_context_columns(self, context_columns):
732
740
  """Process context columns by applying appropriate transformations.
@@ -212,6 +212,13 @@ class BaseSynthesizer:
212
212
  'SYNTHESIZER ID': self._synthesizer_id,
213
213
  })
214
214
 
215
+ def _validate_table_name(self, table_name):
216
+ if table_name != self._table_name:
217
+ raise ValueError(
218
+ 'The provided table name does not match the metadata:'
219
+ f"\nTable '{table_name}' is not present in the metadata."
220
+ )
221
+
215
222
  def _validate_metadata(self, table_data):
216
223
  """Validate that the table data follows the metadata."""
217
224
  errors = []
@@ -293,13 +300,21 @@ class BaseSynthesizer:
293
300
  'parameter to False.'
294
301
  )
295
302
 
296
- def update_transformers(self, column_name_to_transformer):
303
+ def update_transformers(self, column_name_to_transformer, table_name=None):
297
304
  """Update any of the transformers assigned to each of the column names.
298
305
 
299
306
  Args:
300
307
  column_name_to_transformer (dict):
301
308
  Dict mapping column names to transformers to be used for that column.
309
+ table_name (str, optional):
310
+ The name of the table for which to update the transformers. If not provided,
311
+ will use the default table name associated with the synthesizer. Defaults to None.
302
312
  """
313
+ if table_name is not None:
314
+ self._validate_table_name(table_name)
315
+ else:
316
+ table_name = self._table_name
317
+
303
318
  self._validate_transformers(column_name_to_transformer)
304
319
  self._warn_quality_and_performance(column_name_to_transformer)
305
320
  self._warn_unable_to_enforce_rounding(column_name_to_transformer)
@@ -358,16 +373,26 @@ class BaseSynthesizer:
358
373
  self.validate(data)
359
374
  self._auto_assign_transformers(data)
360
375
 
361
- def get_transformers(self):
376
+ def get_transformers(self, table_name=None):
362
377
  """Get a dictionary mapping of ``column_name`` and ``rdt.transformers``.
363
378
 
364
379
  A dictionary representing the column names and the transformers that will be used
365
380
  to transform the data.
366
381
 
382
+ Args:
383
+ table_name (str, optional):
384
+ The name of the table for which to get the transformers. If not provided,
385
+ the default table name will be used. Defaults to None.
386
+
367
387
  Returns:
368
388
  dict:
369
389
  A dictionary mapping with column names and transformers.
370
390
  """
391
+ if table_name is not None:
392
+ self._validate_table_name(table_name)
393
+ else:
394
+ table_name = self._table_name
395
+
371
396
  field_transformers = self._data_processor._hyper_transformer.field_transformers
372
397
  if field_transformers == {}:
373
398
  raise ValueError(
@@ -1179,17 +1204,10 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
1179
1204
  ' sampling synthetic data.'
1180
1205
  )
1181
1206
 
1182
- def _validate_table_name(self, table_name):
1183
- if table_name != self._table_name:
1184
- raise ValueError(
1185
- 'The provided table name does not match the metadata:'
1186
- f"\nTable '{table_name}' is not present in the metadata."
1187
- )
1188
-
1189
1207
  def sample(
1190
1208
  self,
1191
- table_name,
1192
1209
  num_rows,
1210
+ main_table_name=None,
1193
1211
  max_tries_per_batch=100,
1194
1212
  batch_size=None,
1195
1213
  output_folder_path=None,
@@ -1197,10 +1215,10 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
1197
1215
  """Sample rows from this table.
1198
1216
 
1199
1217
  Args:
1200
- table_name (str):
1201
- Name of the table to sample. This parameter is required.
1202
1218
  num_rows (int):
1203
1219
  Number of rows to sample. This parameter is required.
1220
+ main_table_name (str):
1221
+ Name of the table to sample.
1204
1222
  max_tries_per_batch (int):
1205
1223
  Number of times to retry sampling until the batch size is met. Defaults to 100.
1206
1224
  batch_size (int or None):
@@ -1213,6 +1231,7 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
1213
1231
  dict[str, pandas.DataFrame]:
1214
1232
  Dictionary mapping the table name to the sampled data.
1215
1233
  """
1234
+ table_name = self._table_name if main_table_name is None else main_table_name
1216
1235
  self._validate_table_name(table_name)
1217
1236
  self._validate_fit_before_sample()
1218
1237
  self._check_input_metadata_updated()
@@ -1422,8 +1441,9 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
1422
1441
  The folder to periodically write sampled rows to. Defaults to None.
1423
1442
 
1424
1443
  Returns:
1425
- pandas.DataFrame:
1426
- Sampled data.
1444
+ dict[str, pandas.DataFrame]:
1445
+ Dictionary mapping the table name to the sampled data.
1446
+
1427
1447
 
1428
1448
  Raises:
1429
1449
  ConstraintsNotMetError:
@@ -1483,7 +1503,7 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
1483
1503
  'TOTAL NUMBER OF COLUMNS': len(sampled.columns),
1484
1504
  })
1485
1505
 
1486
- return sampled
1506
+ return {self._table_name: sampled}
1487
1507
 
1488
1508
  def _validate_known_columns(self, conditions):
1489
1509
  """Validate the user-passed conditions."""
@@ -1507,8 +1527,8 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
1507
1527
  The folder to periodically write sampled rows to. Defaults to None.
1508
1528
 
1509
1529
  Returns:
1510
- pandas.DataFrame:
1511
- Sampled data.
1530
+ dict[str, pandas.DataFrame]:
1531
+ Dictionary mapping the table name to the sampled data.
1512
1532
 
1513
1533
  Raises:
1514
1534
  ConstraintsNotMetError:
@@ -1557,4 +1577,4 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
1557
1577
  'TOTAL NUMBER OF COLUMNS': len(sampled.columns),
1558
1578
  })
1559
1579
 
1560
- return sampled
1580
+ return {self._table_name: sampled}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdv
3
- Version: 2.0.0.dev0
3
+ Version: 2.0.1.dev0
4
4
  Summary: Generate synthetic data for single table, multi table and sequential data
5
5
  Author-email: "DataCebo, Inc." <info@sdv.dev>
6
6
  License-Expression: BUSL-1.1
@@ -14,14 +14,13 @@ Classifier: Development Status :: 5 - Production/Stable
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: Natural Language :: English
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.9
18
17
  Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
21
20
  Classifier: Programming Language :: Python :: 3.13
22
21
  Classifier: Programming Language :: Python :: 3.14
23
22
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
- Requires-Python: <3.15,>=3.9
23
+ Requires-Python: <3.15,>=3.10
25
24
  Description-Content-Type: text/markdown
26
25
  License-File: LICENSE
27
26
  Requires-Dist: boto3<2.0.0,>=1.28
@@ -29,8 +28,7 @@ Requires-Dist: botocore<2.0.0,>=1.31
29
28
  Requires-Dist: cloudpickle>=2.1.0; python_version < "3.14"
30
29
  Requires-Dist: cloudpickle>=3.1.1; python_version >= "3.14"
31
30
  Requires-Dist: graphviz>=0.13.2
32
- Requires-Dist: numpy>=1.22.2; python_version < "3.10"
33
- Requires-Dist: numpy>=1.24.0; python_version >= "3.10" and python_version < "3.12"
31
+ Requires-Dist: numpy>=1.24.0; python_version < "3.12"
34
32
  Requires-Dist: numpy>=1.26.0; python_version >= "3.12" and python_version < "3.13"
35
33
  Requires-Dist: numpy>=2.1.0; python_version >= "3.13" and python_version < "3.14"
36
34
  Requires-Dist: numpy>=2.3.2; python_version >= "3.14"
@@ -46,7 +44,7 @@ Requires-Dist: ctgan>=0.11.1; python_version < "3.14"
46
44
  Requires-Dist: ctgan>=0.12.0; python_version >= "3.14"
47
45
  Requires-Dist: deepecho>=0.7.0; python_version < "3.14"
48
46
  Requires-Dist: deepecho>=0.8.0; python_version >= "3.14"
49
- Requires-Dist: rdt>=2.0.0.dev0
47
+ Requires-Dist: rdt>=2.0.0
50
48
  Requires-Dist: sdmetrics>=0.32.0
51
49
  Requires-Dist: platformdirs>=4.0
52
50
  Requires-Dist: pyyaml>=6.0.1
@@ -64,7 +62,6 @@ Requires-Dist: google-api-python-client; extra == "test"
64
62
  Requires-Dist: google-auth; extra == "test"
65
63
  Requires-Dist: google-auth-oauthlib; extra == "test"
66
64
  Requires-Dist: requests; extra == "test"
67
- Requires-Dist: pyarrow; extra == "test"
68
65
  Requires-Dist: gitpython; extra == "test"
69
66
  Requires-Dist: slack-sdk<4.0,>=3.23; extra == "test"
70
67
  Provides-Extra: pomegranate
@@ -91,6 +88,8 @@ Requires-Dist: coverage<8,>=4.5.12; extra == "dev"
91
88
  Requires-Dist: invoke; extra == "dev"
92
89
  Provides-Extra: readme
93
90
  Requires-Dist: rundoc<0.5,>=0.4.3; extra == "readme"
91
+ Provides-Extra: benchmark
92
+ Requires-Dist: pyarrow; extra == "benchmark"
94
93
  Dynamic: license-file
95
94
 
96
95
  <div align="center">
@@ -2,26 +2,23 @@ boto3<2.0.0,>=1.28
2
2
  botocore<2.0.0,>=1.31
3
3
  graphviz>=0.13.2
4
4
  tqdm>=4.29
5
- rdt>=2.0.0.dev0
5
+ rdt>=2.0.0
6
6
  sdmetrics>=0.32.0
7
7
  platformdirs>=4.0
8
8
  pyyaml>=6.0.1
9
9
 
10
- [:python_version < "3.10"]
11
- numpy>=1.22.2
12
-
13
10
  [:python_version < "3.11"]
14
11
  pandas<3,>=1.4.0
15
12
 
13
+ [:python_version < "3.12"]
14
+ numpy>=1.24.0
15
+
16
16
  [:python_version < "3.14"]
17
17
  cloudpickle>=2.1.0
18
18
  copulas>=0.12.1
19
19
  ctgan>=0.11.1
20
20
  deepecho>=0.7.0
21
21
 
22
- [:python_version >= "3.10" and python_version < "3.12"]
23
- numpy>=1.24.0
24
-
25
22
  [:python_version >= "3.11" and python_version < "3.12"]
26
23
  pandas<3,>=1.5.0
27
24
 
@@ -41,6 +38,9 @@ copulas>=0.14.0
41
38
  ctgan>=0.12.0
42
39
  deepecho>=0.8.0
43
40
 
41
+ [benchmark]
42
+ pyarrow
43
+
44
44
  [dev]
45
45
  sdv[test]
46
46
  build<2,>=1.0.0
@@ -83,6 +83,5 @@ google-api-python-client
83
83
  google-auth
84
84
  google-auth-oauthlib
85
85
  requests
86
- pyarrow
87
86
  gitpython
88
87
  slack-sdk<4.0,>=3.23
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes