rdt 1.4.2.dev0__tar.gz → 1.5.0__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.
- {rdt-1.4.2.dev0 → rdt-1.5.0}/CONTRIBUTING.rst +5 -71
- {rdt-1.4.2.dev0 → rdt-1.5.0}/HISTORY.md +34 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/PKG-INFO +35 -1
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/__init__.py +74 -5
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/categorical.py +3 -3
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/pii.py +2 -2
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/performance.py +6 -6
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/base.py +62 -9
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/boolean.py +19 -7
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/datetime.py +36 -14
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/null.py +41 -25
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/numerical.py +58 -23
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/pii/anonymizer.py +3 -3
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt.egg-info/PKG-INFO +35 -1
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt.egg-info/SOURCES.txt +0 -6
- {rdt-1.4.2.dev0 → rdt-1.5.0}/setup.cfg +1 -1
- {rdt-1.4.2.dev0 → rdt-1.5.0}/setup.py +1 -1
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/contributing.py +0 -69
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/test_hyper_transformer.py +67 -14
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/test_transformers.py +6 -6
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/test_boolean.py +30 -7
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/test_datetime.py +48 -3
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/test_numerical.py +49 -10
- rdt-1.5.0/tests/unit/test___init__.py +194 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/test_hyper_transformer.py +2 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_base.py +89 -6
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_boolean.py +17 -4
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_datetime.py +27 -101
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_null.py +145 -210
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_numerical.py +37 -135
- rdt-1.4.2.dev0/rdt/_addons.py +0 -26
- rdt-1.4.2.dev0/tests/quality/__init__.py +0 -1
- rdt-1.4.2.dev0/tests/quality/dataset_info.csv +0 -465
- rdt-1.4.2.dev0/tests/quality/test_quality.py +0 -251
- rdt-1.4.2.dev0/tests/quality/utils.py +0 -55
- rdt-1.4.2.dev0/tests/unit/test___init__.py +0 -40
- rdt-1.4.2.dev0/tests/unit/test__addons.py +0 -45
- {rdt-1.4.2.dev0 → rdt-1.5.0}/AUTHORS.rst +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/LICENSE +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/MANIFEST.in +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/README.md +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/RELEASE.md +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/errors.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/hyper_transformer.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/base.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/boolean.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/datetime.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/numerical.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/text.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/datasets/utils.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/performance/profiling.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/addons/addons_setup.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/categorical.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/pii/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/pii/utils.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/text.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt/transformers/utils.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt.egg-info/dependency_links.txt +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt.egg-info/not-zip-safe +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt.egg-info/requires.txt +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/rdt.egg-info/top_level.txt +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/code_style.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/datasets/tests/test_boolean.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/datasets/tests/test_categorical.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/datasets/tests/test_datetime.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/datasets/tests/test_numerical.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/datasets/tests/test_utils.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/pii/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/pii/test_anonymizer.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/test_base.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/test_categorical.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/integration/transformers/test_text.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/performance/README.md +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/performance/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/performance/test_performance.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/performance/tests/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/performance/tests/test_profiling.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/addons/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/addons/identity/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/addons/identity/test_identity.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/pii/__init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/pii/test_anonymizer.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/pii/test_utils.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test___init__.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_categorical.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_text.py +0 -0
- {rdt-1.4.2.dev0 → rdt-1.5.0}/tests/unit/transformers/test_utils.py +0 -0
|
@@ -175,10 +175,9 @@ class uses. In some cases, integration tests may also be required. More details
|
|
|
175
175
|
found below.
|
|
176
176
|
|
|
177
177
|
If the transformer adds a previously unsupported `sdtype` to RDT, then more steps will need
|
|
178
|
-
to be taken for
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
the `Transformer Performance`_ and `Transformer Quality`_ sections respectively.
|
|
178
|
+
to be taken for performance tests. A new `DatasetGenerator` class may need to be created for
|
|
179
|
+
the `sdtype`. More details for these steps can be found below in the `Transformer Performance`_
|
|
180
|
+
section.
|
|
182
181
|
|
|
183
182
|
Transformer Validations
|
|
184
183
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -418,64 +417,6 @@ of the transformer.
|
|
|
418
417
|
Fix any performance issues that are reported. If there are no errors but performance
|
|
419
418
|
can be improved, this function should be used for reference.
|
|
420
419
|
|
|
421
|
-
.. _Transformer Quality:
|
|
422
|
-
|
|
423
|
-
Transformer Quality
|
|
424
|
-
"""""""""""""""""""
|
|
425
|
-
|
|
426
|
-
To assess the quality of a transformer, we run quality tests that apply the Transformer
|
|
427
|
-
on all the real world datasets that contain the Transformer input sdtype. The quality tests
|
|
428
|
-
look at how well the original correlations are preserved by using transformed data to train
|
|
429
|
-
regression models that predict other columns in the data. We compare the transformer's quality
|
|
430
|
-
results to that of other transformers of the same sdtype.
|
|
431
|
-
|
|
432
|
-
.. _Adding a Dataset:
|
|
433
|
-
|
|
434
|
-
Adding a Dataset
|
|
435
|
-
****************
|
|
436
|
-
|
|
437
|
-
If the transformer you are creating adds a new sdtype, then a dataset with that sdtype may need to
|
|
438
|
-
be added for the quality tests. This only needs to be done if the transformer being added is
|
|
439
|
-
expected to preserve or expose relationships in the data. This can be done using the following
|
|
440
|
-
steps:
|
|
441
|
-
|
|
442
|
-
1. Find a dataset containing the sdtype your transformer uses as an input.
|
|
443
|
-
|
|
444
|
-
2. Test your transformer against this dataset by loading it into a ``DataFrame`` and using the
|
|
445
|
-
``get_transformer_regression_scores`` in the ``test_quality`` package::
|
|
446
|
-
|
|
447
|
-
from tests.quality.test_quality import get_transformer_regression_scores
|
|
448
|
-
get_transformer_regression_scores(data, sdtype, dataset_name, [transformer])
|
|
449
|
-
|
|
450
|
-
3. If the scores are higher than the ``TEST_THRESHOLD`` in the ``test_quality`` package, contact
|
|
451
|
-
one of the `RDT core contributors`_ on GitHub and ask them to add the dataset. Once this is
|
|
452
|
-
done, the quality tests should pass.
|
|
453
|
-
|
|
454
|
-
Validating Quality
|
|
455
|
-
******************
|
|
456
|
-
|
|
457
|
-
Validate the quality of your transformer using the ``validate_transformer_quality`` function.
|
|
458
|
-
This function returns a ``pandas.DataFrame`` containing the scores attained by the transformer
|
|
459
|
-
on each dataset, how that score compares to average and whether or not it is acceptable.
|
|
460
|
-
|
|
461
|
-
.. code-block:: Python
|
|
462
|
-
|
|
463
|
-
In [1]: from tests.contributing import validate_transformer_quality
|
|
464
|
-
|
|
465
|
-
In [2]: results = validate_transformer_quality('rdt.transformers.FrequencyEncoder') # Replace FrequencyEncoder with your transformer
|
|
466
|
-
Validating Quality Tests for transformer FrequencyEncoder
|
|
467
|
-
|
|
468
|
-
SUCCESS: The quality tests were successful.
|
|
469
|
-
|
|
470
|
-
In [3]: results
|
|
471
|
-
Out [3]:
|
|
472
|
-
Dataset Score Compared To Average Acceptable
|
|
473
|
-
0 adult 0.223325 0.443181 True
|
|
474
|
-
1 student_placements 0.457490 0.994631 True
|
|
475
|
-
2 student_placements_pii 0.457490 0.988428 True
|
|
476
|
-
|
|
477
|
-
Fix any quality issues that are reported.
|
|
478
|
-
|
|
479
420
|
Finalize Your Transformer
|
|
480
421
|
"""""""""""""""""""""""""
|
|
481
422
|
|
|
@@ -496,7 +437,6 @@ above. It also prints a table summarizing the results of all these checks.
|
|
|
496
437
|
Unit Tests Yes The unit tests are correct and run successfully.
|
|
497
438
|
Integration tests Yes The integration tests run successfully.
|
|
498
439
|
Performance Tests Yes The performance of the transformer is acceptable.
|
|
499
|
-
Quality tests Yes The output data quality is acceptable.
|
|
500
440
|
Clean Repository Yes There are no unexpected changes in the repository.
|
|
501
441
|
|
|
502
442
|
SUCCESS: The Pull Request can be made!
|
|
@@ -528,14 +468,8 @@ Summary of Steps to Add a New Transformer
|
|
|
528
468
|
10. Run the ``validate_transformer_performance`` function and fix any errors reported.
|
|
529
469
|
If there are no errors but performance can be improved, this function should be used for
|
|
530
470
|
reference.
|
|
531
|
-
11.
|
|
532
|
-
|
|
533
|
-
necessary enhancements to the transformer.
|
|
534
|
-
12. If the quality tests fail because there is no dataset for the transformer's sdtype,
|
|
535
|
-
follow the steps in the `Adding a Dataset`_ section to add a real world dataset
|
|
536
|
-
containing the new sdtype to the quality tests.
|
|
537
|
-
13. Run the ``validate_pull_request`` function as a final check and fix any errors reported.
|
|
538
|
-
14. After all the previous steps pass, all the new and modified files can be committed and pushed
|
|
471
|
+
11. Run the ``validate_pull_request`` function as a final check and fix any errors reported.
|
|
472
|
+
12. After all the previous steps pass, all the new and modified files can be committed and pushed
|
|
539
473
|
to github, and a Pull Request can be submitted. Follow the steps in the
|
|
540
474
|
`Pull Request Guidelines`_ section to submit your Pull Request.
|
|
541
475
|
|
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# History
|
|
2
2
|
|
|
3
|
+
## 1.5.0 - 2023-06-01
|
|
4
|
+
|
|
5
|
+
This release adds a new parameter called `missing_value_generation` to the initialization of certain transformers to specify how missing values should be created. The parameter can be used in the `FloatFormatter`, `BinaryEncoder`, `UnixTimestampEncoder`, `OptimizedTimestampEncoder`, `GaussianNormalizer` and `ClusterBasedNormalizer`. Additionally, it fixes a bug that was causing every column that had nulls to generate them in the same place.
|
|
6
|
+
|
|
7
|
+
### Deprecations
|
|
8
|
+
|
|
9
|
+
* The `model_missing_values` parameter is being deprecated in favor of the new `missing_value_generation` parameter.
|
|
10
|
+
|
|
11
|
+
### Bugs
|
|
12
|
+
|
|
13
|
+
* Fix randomization when creating null values - Issue [#639](https://github.com/sdv-dev/RDT/issues/639) by @fealho
|
|
14
|
+
|
|
15
|
+
### New Features
|
|
16
|
+
|
|
17
|
+
* Allow a no-op handling strategy for missing values (nulls) - Issue [#644](https://github.com/sdv-dev/RDT/issues/644) by @pvk-developer
|
|
18
|
+
* Add add-on detection for premium transformers - Issue [#646](https://github.com/sdv-dev/RDT/issues/646) by @frances-h
|
|
19
|
+
|
|
20
|
+
### Maintenance
|
|
21
|
+
|
|
22
|
+
* Performance tests still fragile - Issue [#641](https://github.com/sdv-dev/RDT/issues/641) by @fealho
|
|
23
|
+
* Investigate removing quality tests - Issue [#642](https://github.com/sdv-dev/RDT/issues/642) by @amontanez24
|
|
24
|
+
|
|
25
|
+
## 1.4.2 - 2023-05-02
|
|
26
|
+
|
|
27
|
+
This release fixes a bug that caused datetime and numerical transformers to crash if a column was all NaNs. Additionally, it adds support for Pandas 2.0!
|
|
28
|
+
|
|
29
|
+
### Bugs
|
|
30
|
+
|
|
31
|
+
* Numerical & datetime transformers crash if the entire column is null - Issue [#637](https://github.com/sdv-dev/RDT/issues/637) by @fraces-h
|
|
32
|
+
|
|
33
|
+
### Maintenance
|
|
34
|
+
|
|
35
|
+
* Remove upper bound for pandas - Issue [#633](https://github.com/sdv-dev/RDT/issues/633) by @pvk-developer
|
|
36
|
+
|
|
3
37
|
## 1.4.1 - 2023-04-25
|
|
4
38
|
|
|
5
39
|
This release patches an issue that prevented the `RegexGenerator` from working with regexes that had a very large number of possible combinations.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rdt
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Reversible Data Transforms
|
|
5
5
|
Home-page: https://github.com/sdv-dev/RDT
|
|
6
6
|
Author: DataCebo, Inc.
|
|
@@ -226,6 +226,40 @@ for specific needs.
|
|
|
226
226
|
|
|
227
227
|
# History
|
|
228
228
|
|
|
229
|
+
## 1.5.0 - 2023-06-01
|
|
230
|
+
|
|
231
|
+
This release adds a new parameter called `missing_value_generation` to the initialization of certain transformers to specify how missing values should be created. The parameter can be used in the `FloatFormatter`, `BinaryEncoder`, `UnixTimestampEncoder`, `OptimizedTimestampEncoder`, `GaussianNormalizer` and `ClusterBasedNormalizer`. Additionally, it fixes a bug that was causing every column that had nulls to generate them in the same place.
|
|
232
|
+
|
|
233
|
+
### Deprecations
|
|
234
|
+
|
|
235
|
+
* The `model_missing_values` parameter is being deprecated in favor of the new `missing_value_generation` parameter.
|
|
236
|
+
|
|
237
|
+
### Bugs
|
|
238
|
+
|
|
239
|
+
* Fix randomization when creating null values - Issue [#639](https://github.com/sdv-dev/RDT/issues/639) by @fealho
|
|
240
|
+
|
|
241
|
+
### New Features
|
|
242
|
+
|
|
243
|
+
* Allow a no-op handling strategy for missing values (nulls) - Issue [#644](https://github.com/sdv-dev/RDT/issues/644) by @pvk-developer
|
|
244
|
+
* Add add-on detection for premium transformers - Issue [#646](https://github.com/sdv-dev/RDT/issues/646) by @frances-h
|
|
245
|
+
|
|
246
|
+
### Maintenance
|
|
247
|
+
|
|
248
|
+
* Performance tests still fragile - Issue [#641](https://github.com/sdv-dev/RDT/issues/641) by @fealho
|
|
249
|
+
* Investigate removing quality tests - Issue [#642](https://github.com/sdv-dev/RDT/issues/642) by @amontanez24
|
|
250
|
+
|
|
251
|
+
## 1.4.2 - 2023-05-02
|
|
252
|
+
|
|
253
|
+
This release fixes a bug that caused datetime and numerical transformers to crash if a column was all NaNs. Additionally, it adds support for Pandas 2.0!
|
|
254
|
+
|
|
255
|
+
### Bugs
|
|
256
|
+
|
|
257
|
+
* Numerical & datetime transformers crash if the entire column is null - Issue [#637](https://github.com/sdv-dev/RDT/issues/637) by @fraces-h
|
|
258
|
+
|
|
259
|
+
### Maintenance
|
|
260
|
+
|
|
261
|
+
* Remove upper bound for pandas - Issue [#633](https://github.com/sdv-dev/RDT/issues/633) by @pvk-developer
|
|
262
|
+
|
|
229
263
|
## 1.4.1 - 2023-04-25
|
|
230
264
|
|
|
231
265
|
This release patches an issue that prevented the `RegexGenerator` from working with regexes that had a very large number of possible combinations.
|
|
@@ -5,14 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
__author__ = 'DataCebo, Inc.'
|
|
7
7
|
__email__ = 'info@sdv.dev'
|
|
8
|
-
__version__ = '1.
|
|
8
|
+
__version__ = '1.5.0'
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
import sys
|
|
12
|
+
import warnings
|
|
13
|
+
from operator import attrgetter
|
|
14
|
+
|
|
11
15
|
import numpy as np
|
|
12
16
|
import pandas as pd
|
|
17
|
+
from pkg_resources import iter_entry_points
|
|
13
18
|
|
|
14
19
|
from rdt import transformers
|
|
15
|
-
from rdt._addons import _find_addons
|
|
16
20
|
from rdt.hyper_transformer import HyperTransformer
|
|
17
21
|
|
|
18
22
|
__all__ = [
|
|
@@ -23,9 +27,6 @@ __all__ = [
|
|
|
23
27
|
RANDOM_SEED = 42
|
|
24
28
|
|
|
25
29
|
|
|
26
|
-
_find_addons(group='rdt_modules', parent_globals=globals())
|
|
27
|
-
|
|
28
|
-
|
|
29
30
|
def get_demo(num_rows=5):
|
|
30
31
|
"""Generate demo data with multiple sdtypes.
|
|
31
32
|
|
|
@@ -92,3 +93,71 @@ def get_demo(num_rows=5):
|
|
|
92
93
|
'dollars_spent': dollars_spent
|
|
93
94
|
})
|
|
94
95
|
], ignore_index=True)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _get_addon_target(addon_path_name):
|
|
99
|
+
"""Find the target object for the add-on.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
addon_path_name (str):
|
|
103
|
+
The add-on's name. The add-on's name should be the full path of valid Python
|
|
104
|
+
identifiers (i.e. importable.module:object.attr).
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
tuple:
|
|
108
|
+
* object:
|
|
109
|
+
The base module or object the add-on should be added to.
|
|
110
|
+
* str:
|
|
111
|
+
The name the add-on should be added to under the module or object.
|
|
112
|
+
"""
|
|
113
|
+
module_path, _, object_path = addon_path_name.partition(':')
|
|
114
|
+
module_path = module_path.split('.')
|
|
115
|
+
|
|
116
|
+
if module_path[0] != __name__:
|
|
117
|
+
msg = f"expected base module to be '{__name__}', found '{module_path[0]}'"
|
|
118
|
+
raise AttributeError(msg)
|
|
119
|
+
|
|
120
|
+
target_base = sys.modules[__name__]
|
|
121
|
+
for submodule in module_path[1:-1]:
|
|
122
|
+
target_base = getattr(target_base, submodule)
|
|
123
|
+
|
|
124
|
+
addon_name = module_path[-1]
|
|
125
|
+
if object_path:
|
|
126
|
+
if len(module_path) > 1 and not hasattr(target_base, module_path[-1]):
|
|
127
|
+
msg = f"cannot add '{object_path}' to unknown submodule '{'.'.join(module_path)}'"
|
|
128
|
+
raise AttributeError(msg)
|
|
129
|
+
|
|
130
|
+
if len(module_path) > 1:
|
|
131
|
+
target_base = getattr(target_base, module_path[-1])
|
|
132
|
+
|
|
133
|
+
split_object = object_path.split('.')
|
|
134
|
+
addon_name = split_object[-1]
|
|
135
|
+
|
|
136
|
+
if len(split_object) > 1:
|
|
137
|
+
target_base = attrgetter('.'.join(split_object[:-1]))(target_base)
|
|
138
|
+
|
|
139
|
+
return target_base, addon_name
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _find_addons():
|
|
143
|
+
"""Find and load all RDT add-ons."""
|
|
144
|
+
group = 'rdt_modules'
|
|
145
|
+
for entry_point in iter_entry_points(group=group):
|
|
146
|
+
try:
|
|
147
|
+
addon = entry_point.load()
|
|
148
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
149
|
+
msg = f'Failed to load "{entry_point.name}" from "{entry_point.module_name}".'
|
|
150
|
+
warnings.warn(msg)
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
addon_target, addon_name = _get_addon_target(entry_point.name)
|
|
155
|
+
except AttributeError as error:
|
|
156
|
+
msg = f"Failed to set '{entry_point.name}': {error}."
|
|
157
|
+
warnings.warn(msg)
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
setattr(addon_target, addon_name, addon)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
_find_addons()
|
|
@@ -335,7 +335,7 @@ class UniqueIntegerGenerator(CategoricalGenerator):
|
|
|
335
335
|
'memory': 500000.0
|
|
336
336
|
},
|
|
337
337
|
'reverse_transform': {
|
|
338
|
-
'time': 0.
|
|
338
|
+
'time': 0.0005,
|
|
339
339
|
'memory': 1000000.0,
|
|
340
340
|
}
|
|
341
341
|
}
|
|
@@ -362,7 +362,7 @@ class UniqueIntegerNaNsGenerator(CategoricalGenerator):
|
|
|
362
362
|
'memory': 1000000.0
|
|
363
363
|
},
|
|
364
364
|
'reverse_transform': {
|
|
365
|
-
'time': 0.
|
|
365
|
+
'time': 0.0005,
|
|
366
366
|
'memory': 1000000.0,
|
|
367
367
|
}
|
|
368
368
|
}
|
|
@@ -389,7 +389,7 @@ class UniqueStringGenerator(CategoricalGenerator):
|
|
|
389
389
|
'memory': 500000.0
|
|
390
390
|
},
|
|
391
391
|
'reverse_transform': {
|
|
392
|
-
'time': 0.
|
|
392
|
+
'time': 0.0005,
|
|
393
393
|
'memory': 1000000.0,
|
|
394
394
|
}
|
|
395
395
|
}
|
|
@@ -36,7 +36,7 @@ class RandomStringGenerator(PIIGenerator):
|
|
|
36
36
|
'memory': 500.0
|
|
37
37
|
},
|
|
38
38
|
'reverse_transform': {
|
|
39
|
-
'time':
|
|
39
|
+
'time': 3e-05,
|
|
40
40
|
'memory': 1000.0,
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -63,7 +63,7 @@ class RandomStringNaNsGenerator(PIIGenerator):
|
|
|
63
63
|
'memory': 1000.0
|
|
64
64
|
},
|
|
65
65
|
'reverse_transform': {
|
|
66
|
-
'time':
|
|
66
|
+
'time': 3e-05,
|
|
67
67
|
'memory': 1000.0,
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -11,22 +11,22 @@ DATASET_SIZES = [1000, 10000, 100000]
|
|
|
11
11
|
TRANSFORMER_ARGS = {
|
|
12
12
|
'BinaryEncoder': {
|
|
13
13
|
'missing_value_replacement': -1,
|
|
14
|
-
'
|
|
14
|
+
'missing_value_generation': 'from_column'
|
|
15
15
|
},
|
|
16
16
|
'UnixTimestampEncoder': {
|
|
17
|
-
'
|
|
17
|
+
'missing_value_generation': 'from_column'
|
|
18
18
|
},
|
|
19
19
|
'OptimizedTimestampEncoder': {
|
|
20
|
-
'
|
|
20
|
+
'missing_value_generation': 'from_column'
|
|
21
21
|
},
|
|
22
22
|
'FloatFormatter': {
|
|
23
|
-
'
|
|
23
|
+
'missing_value_generation': 'from_column'
|
|
24
24
|
},
|
|
25
25
|
'GaussianNormalizer': {
|
|
26
|
-
'
|
|
26
|
+
'missing_value_generation': 'from_column'
|
|
27
27
|
},
|
|
28
28
|
'ClusterBasedNormalizer': {
|
|
29
|
-
'
|
|
29
|
+
'missing_value_generation': 'from_column'
|
|
30
30
|
},
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""BaseTransformer module."""
|
|
2
2
|
import abc
|
|
3
3
|
import contextlib
|
|
4
|
+
import hashlib
|
|
4
5
|
import inspect
|
|
5
6
|
import warnings
|
|
6
7
|
from functools import wraps
|
|
@@ -8,6 +9,8 @@ from functools import wraps
|
|
|
8
9
|
import numpy as np
|
|
9
10
|
import pandas as pd
|
|
10
11
|
|
|
12
|
+
from rdt.errors import TransformerInputError
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
@contextlib.contextmanager
|
|
13
16
|
def set_random_states(random_states, method_name, set_model_random_state):
|
|
@@ -65,21 +68,21 @@ class BaseTransformer:
|
|
|
65
68
|
INPUT_SDTYPE = None
|
|
66
69
|
SUPPORTED_SDTYPES = None
|
|
67
70
|
IS_GENERATOR = None
|
|
68
|
-
INITIAL_FIT_STATE = np.random.RandomState(
|
|
69
|
-
INITIAL_TRANSFORM_STATE = np.random.RandomState(seed=80)
|
|
70
|
-
INITIAL_REVERSE_TRANSFORM_STATE = np.random.RandomState(seed=130)
|
|
71
|
+
INITIAL_FIT_STATE = np.random.RandomState(42)
|
|
71
72
|
|
|
72
73
|
columns = None
|
|
73
74
|
column_prefix = None
|
|
74
75
|
output_columns = None
|
|
76
|
+
random_seed = 42
|
|
75
77
|
missing_value_replacement = None
|
|
78
|
+
missing_value_generation = None
|
|
76
79
|
|
|
77
80
|
def __init__(self):
|
|
78
81
|
self.output_properties = {None: {'sdtype': 'float', 'next_transformer': None}}
|
|
79
82
|
self.random_states = {
|
|
80
83
|
'fit': self.INITIAL_FIT_STATE,
|
|
81
|
-
'transform':
|
|
82
|
-
'reverse_transform':
|
|
84
|
+
'transform': None,
|
|
85
|
+
'reverse_transform': None
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
def set_random_state(self, state, method_name):
|
|
@@ -100,9 +103,41 @@ class BaseTransformer:
|
|
|
100
103
|
|
|
101
104
|
def reset_randomization(self):
|
|
102
105
|
"""Reset the random state for ``reverse_transform``."""
|
|
103
|
-
self.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
self.random_states = {
|
|
107
|
+
'fit': self.INITIAL_FIT_STATE,
|
|
108
|
+
'transform': np.random.RandomState(self.random_seed),
|
|
109
|
+
'reverse_transform': np.random.RandomState(self.random_seed + 1)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def model_missing_values(self):
|
|
114
|
+
"""Return whether or not a new column is being used to model missing values."""
|
|
115
|
+
warnings.warn(
|
|
116
|
+
"Future versions of RDT will not support the 'model_missing_values' parameter. "
|
|
117
|
+
"Please switch to using the 'missing_value_generation' parameter instead.",
|
|
118
|
+
FutureWarning
|
|
119
|
+
)
|
|
120
|
+
return self.missing_value_generation == 'from_column'
|
|
121
|
+
|
|
122
|
+
def _set_missing_value_generation(self, missing_value_generation):
|
|
123
|
+
if missing_value_generation not in (None, 'from_column', 'random'):
|
|
124
|
+
raise TransformerInputError(
|
|
125
|
+
"'missing_value_generation' must be one of the following values: "
|
|
126
|
+
"None, 'from_column' or 'random'."
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
self.missing_value_generation = missing_value_generation
|
|
130
|
+
|
|
131
|
+
def _set_model_missing_values(self, model_missing_values):
|
|
132
|
+
warnings.warn(
|
|
133
|
+
"Future versions of RDT will not support the 'model_missing_values' parameter. "
|
|
134
|
+
"Please switch to using the 'missing_value_generation' parameter to select your "
|
|
135
|
+
'strategy.', FutureWarning
|
|
136
|
+
)
|
|
137
|
+
if model_missing_values is True:
|
|
138
|
+
self._set_missing_value_generation('from_column')
|
|
139
|
+
elif model_missing_values is False:
|
|
140
|
+
self._set_missing_value_generation('random')
|
|
106
141
|
|
|
107
142
|
def _set_missing_value_replacement(self, default, missing_value_replacement):
|
|
108
143
|
if missing_value_replacement is None:
|
|
@@ -297,7 +332,11 @@ class BaseTransformer:
|
|
|
297
332
|
keys = args.args[1:]
|
|
298
333
|
defaults = args.defaults or []
|
|
299
334
|
defaults = dict(zip(keys, defaults))
|
|
300
|
-
instanced = {
|
|
335
|
+
instanced = {
|
|
336
|
+
key: getattr(self, key)
|
|
337
|
+
for key in keys
|
|
338
|
+
if key != 'model_missing_values' # Remove after deprecation
|
|
339
|
+
}
|
|
301
340
|
|
|
302
341
|
if defaults == instanced:
|
|
303
342
|
return f'{class_name}()'
|
|
@@ -318,6 +357,19 @@ class BaseTransformer:
|
|
|
318
357
|
"""
|
|
319
358
|
raise NotImplementedError()
|
|
320
359
|
|
|
360
|
+
def _set_seed(self, data):
|
|
361
|
+
hash_value = self.get_input_column()
|
|
362
|
+
for value in data.head(5):
|
|
363
|
+
hash_value += str(value)
|
|
364
|
+
|
|
365
|
+
hash_value = int(hashlib.sha256(hash_value.encode('utf-8')).hexdigest(), 16)
|
|
366
|
+
self.random_seed = hash_value % ((2 ** 32) - 1) # maximum value for a seed
|
|
367
|
+
self.random_states = {
|
|
368
|
+
'fit': self.INITIAL_FIT_STATE,
|
|
369
|
+
'transform': np.random.RandomState(self.random_seed),
|
|
370
|
+
'reverse_transform': np.random.RandomState(self.random_seed + 1)
|
|
371
|
+
}
|
|
372
|
+
|
|
321
373
|
@random_state
|
|
322
374
|
def fit(self, data, column):
|
|
323
375
|
"""Fit the transformer to a ``column`` of the ``data``.
|
|
@@ -329,6 +381,7 @@ class BaseTransformer:
|
|
|
329
381
|
Column name. Must be present in the data.
|
|
330
382
|
"""
|
|
331
383
|
self._store_columns(column, data)
|
|
384
|
+
self._set_seed(data)
|
|
332
385
|
columns_data = self._get_columns_data(data, self.columns)
|
|
333
386
|
self._fit(columns_data)
|
|
334
387
|
self._build_output_columns(data)
|
|
@@ -21,19 +21,31 @@ class BinaryEncoder(BaseTransformer):
|
|
|
21
21
|
replace them with the most common value.
|
|
22
22
|
Defaults to ``mode``.
|
|
23
23
|
model_missing_values (bool):
|
|
24
|
-
Whether to create a new column to indicate which values were null or
|
|
25
|
-
will be created only if there are null values. If ``True``, create
|
|
26
|
-
there are null values. If ``False``, do not create the new column
|
|
27
|
-
are null values. Defaults to ``False``.
|
|
24
|
+
**DEPRECATED** Whether to create a new column to indicate which values were null or
|
|
25
|
+
not. The column will be created only if there are null values. If ``True``, create
|
|
26
|
+
the new column if there are null values. If ``False``, do not create the new column
|
|
27
|
+
even if there are null values. Defaults to ``False``.
|
|
28
|
+
missing_value_generation (str or None):
|
|
29
|
+
The way missing values are being handled. There are three strategies:
|
|
30
|
+
|
|
31
|
+
* ``random``: Randomly generates missing values based on the percentage of
|
|
32
|
+
missing values.
|
|
33
|
+
* ``from_column``: Creates a binary column that describes whether the original
|
|
34
|
+
value was missing. Then use it to recreate missing values.
|
|
35
|
+
* ``None``: Do nothing with the missing values on the reverse transform. Simply
|
|
36
|
+
pass whatever data we get through.
|
|
28
37
|
"""
|
|
29
38
|
|
|
30
39
|
INPUT_SDTYPE = 'boolean'
|
|
31
40
|
null_transformer = None
|
|
32
41
|
|
|
33
|
-
def __init__(self, missing_value_replacement='mode', model_missing_values=
|
|
42
|
+
def __init__(self, missing_value_replacement='mode', model_missing_values=None,
|
|
43
|
+
missing_value_generation='random'):
|
|
34
44
|
super().__init__()
|
|
45
|
+
self._set_missing_value_generation(missing_value_generation)
|
|
35
46
|
self._set_missing_value_replacement('mode', missing_value_replacement)
|
|
36
|
-
|
|
47
|
+
if model_missing_values is not None:
|
|
48
|
+
self._set_model_missing_values(model_missing_values)
|
|
37
49
|
|
|
38
50
|
def _fit(self, data):
|
|
39
51
|
"""Fit the transformer to the data.
|
|
@@ -44,7 +56,7 @@ class BinaryEncoder(BaseTransformer):
|
|
|
44
56
|
"""
|
|
45
57
|
self.null_transformer = NullTransformer(
|
|
46
58
|
self.missing_value_replacement,
|
|
47
|
-
self.
|
|
59
|
+
self.missing_value_generation
|
|
48
60
|
)
|
|
49
61
|
self.null_transformer.fit(data)
|
|
50
62
|
if self.null_transformer.models_missing_values():
|
|
@@ -22,23 +22,35 @@ class UnixTimestampEncoder(BaseTransformer):
|
|
|
22
22
|
are given, replace them with the corresponding aggregation.
|
|
23
23
|
Defaults to ``mean``.
|
|
24
24
|
model_missing_values (bool):
|
|
25
|
-
Whether to create a new column to indicate which values were null or
|
|
26
|
-
will be created only if there are null values. If ``True``, create
|
|
27
|
-
there are null values. If ``False``, do not create the new column
|
|
28
|
-
are null values. Defaults to ``False``.
|
|
25
|
+
**DEPRECATED** Whether to create a new column to indicate which values were null or
|
|
26
|
+
not. The column will be created only if there are null values. If ``True``, create
|
|
27
|
+
the new column if there are null values. If ``False``, do not create the new column
|
|
28
|
+
even if there are null values. Defaults to ``False``.
|
|
29
29
|
datetime_format (str):
|
|
30
30
|
The strftime to use for parsing time. For more information, see
|
|
31
31
|
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior.
|
|
32
|
+
missing_value_generation (str or None):
|
|
33
|
+
The way missing values are being handled. There are three strategies:
|
|
34
|
+
|
|
35
|
+
* ``random``: Randomly generates missing values based on the percentage of
|
|
36
|
+
missing values.
|
|
37
|
+
* ``from_column``: Creates a binary column that describes whether the original
|
|
38
|
+
value was missing. Then use it to recreate missing values.
|
|
39
|
+
* ``None``: Do nothing with the missing values on the reverse transform. Simply
|
|
40
|
+
pass whatever data we get through.
|
|
32
41
|
"""
|
|
33
42
|
|
|
34
43
|
INPUT_SDTYPE = 'datetime'
|
|
35
44
|
null_transformer = None
|
|
36
45
|
|
|
37
|
-
def __init__(self, missing_value_replacement='mean', model_missing_values=
|
|
38
|
-
datetime_format=None):
|
|
46
|
+
def __init__(self, missing_value_replacement='mean', model_missing_values=None,
|
|
47
|
+
datetime_format=None, missing_value_generation='random'):
|
|
39
48
|
super().__init__()
|
|
40
49
|
self._set_missing_value_replacement('mean', missing_value_replacement)
|
|
41
|
-
self.
|
|
50
|
+
self._set_missing_value_generation(missing_value_generation)
|
|
51
|
+
if model_missing_values is not None:
|
|
52
|
+
self._set_model_missing_values(model_missing_values)
|
|
53
|
+
|
|
42
54
|
self.datetime_format = datetime_format
|
|
43
55
|
self._dtype = None
|
|
44
56
|
|
|
@@ -94,7 +106,7 @@ class UnixTimestampEncoder(BaseTransformer):
|
|
|
94
106
|
transformed = self._transform_helper(data)
|
|
95
107
|
self.null_transformer = NullTransformer(
|
|
96
108
|
self.missing_value_replacement,
|
|
97
|
-
self.
|
|
109
|
+
self.missing_value_generation
|
|
98
110
|
)
|
|
99
111
|
self.null_transformer.fit(transformed)
|
|
100
112
|
if self.null_transformer.models_missing_values():
|
|
@@ -156,20 +168,30 @@ class OptimizedTimestampEncoder(UnixTimestampEncoder):
|
|
|
156
168
|
are given, replace them with the corresponding aggregation.
|
|
157
169
|
Defaults to ``mean``.
|
|
158
170
|
model_missing_values (bool):
|
|
159
|
-
Whether to create a new column to indicate which values were null or
|
|
160
|
-
will be created only if there are null values. If ``True``, create
|
|
161
|
-
there are null values. If ``False``, do not create the new column
|
|
162
|
-
are null values. Defaults to ``False``.
|
|
171
|
+
**DEPRECATED** Whether to create a new column to indicate which values were null or
|
|
172
|
+
not. The column will be created only if there are null values. If ``True``, create
|
|
173
|
+
the new column if there are null values. If ``False``, do not create the new column
|
|
174
|
+
even if there are null values. Defaults to ``False``.
|
|
163
175
|
datetime_format (str):
|
|
164
176
|
The strftime to use for parsing time. For more information, see
|
|
165
177
|
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior.
|
|
178
|
+
missing_value_generation (str or None):
|
|
179
|
+
The way missing values are being handled. There are three strategies:
|
|
180
|
+
|
|
181
|
+
* ``random``: Randomly generates missing values based on the percentage of
|
|
182
|
+
missing values.
|
|
183
|
+
* ``from_column``: Creates a binary column that describes whether the original
|
|
184
|
+
value was missing. Then use it to recreate missing values.
|
|
185
|
+
* ``None``: Do nothing with the missing values on the reverse transform. Simply
|
|
186
|
+
pass whatever data we get through.
|
|
166
187
|
"""
|
|
167
188
|
|
|
168
189
|
divider = None
|
|
169
190
|
|
|
170
|
-
def __init__(self, missing_value_replacement=None, model_missing_values=
|
|
171
|
-
datetime_format=None):
|
|
191
|
+
def __init__(self, missing_value_replacement=None, model_missing_values=None,
|
|
192
|
+
datetime_format=None, missing_value_generation='random'):
|
|
172
193
|
super().__init__(missing_value_replacement=missing_value_replacement,
|
|
194
|
+
missing_value_generation=missing_value_generation,
|
|
173
195
|
model_missing_values=model_missing_values,
|
|
174
196
|
datetime_format=datetime_format)
|
|
175
197
|
|