rdt 1.16.0.dev0__tar.gz → 1.17.0.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.
- {rdt-1.16.0.dev0/rdt.egg-info → rdt-1.17.0.dev0}/PKG-INFO +2 -1
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/pyproject.toml +2 -1
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/__init__.py +1 -1
- rdt-1.17.0.dev0/rdt/_utils.py +47 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/hyper_transformer.py +33 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/datetime.py +111 -50
- rdt-1.17.0.dev0/rdt/transformers/id.py +446 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/pii/anonymizer.py +115 -51
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/utils.py +133 -3
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0/rdt.egg-info}/PKG-INFO +2 -1
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt.egg-info/SOURCES.txt +1 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt.egg-info/requires.txt +1 -0
- rdt-1.16.0.dev0/rdt/transformers/id.py +0 -285
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/LICENSE +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/README.md +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/errors.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/__init__.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/__init__.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/base.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/boolean.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/categorical.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/datetime.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/id.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/numerical.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/pii.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/text.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/datasets/utils.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/performance.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/performance/profiling.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/__init__.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/_validators.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/base.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/boolean.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/categorical.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/null.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/numerical.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/pii/__init__.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/pii/anonymization.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/pii/utils.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt/transformers/text.py +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt.egg-info/dependency_links.txt +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt.egg-info/entry_points.txt +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/rdt.egg-info/top_level.txt +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/setup.cfg +0 -0
- {rdt-1.16.0.dev0 → rdt-1.17.0.dev0}/tests/test_tasks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rdt
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17.0.dev0
|
|
4
4
|
Summary: Reversible Data Transforms
|
|
5
5
|
Author-email: "DataCebo, Inc." <info@sdv.dev>
|
|
6
6
|
License: BSL-1.1
|
|
@@ -43,6 +43,7 @@ Requires-Dist: scikit-learn>=1.1.3; python_version >= "3.11" and python_version
|
|
|
43
43
|
Requires-Dist: scikit-learn>=1.3.1; python_version >= "3.12" and python_version < "3.13"
|
|
44
44
|
Requires-Dist: scikit-learn>=1.5.2; python_version >= "3.13"
|
|
45
45
|
Requires-Dist: Faker>=17
|
|
46
|
+
Requires-Dist: python-dateutil>=2.9
|
|
46
47
|
Provides-Extra: copulas
|
|
47
48
|
Requires-Dist: copulas>=0.12.1; extra == "copulas"
|
|
48
49
|
Provides-Extra: pyarrow
|
|
@@ -40,6 +40,7 @@ dependencies = [
|
|
|
40
40
|
"scikit-learn>=1.3.1;python_version>='3.12' and python_version<'3.13'",
|
|
41
41
|
"scikit-learn>=1.5.2;python_version>='3.13'",
|
|
42
42
|
'Faker>=17',
|
|
43
|
+
'python-dateutil>=2.9',
|
|
43
44
|
]
|
|
44
45
|
|
|
45
46
|
[project.urls]
|
|
@@ -144,7 +145,7 @@ collect_ignore = ['pyproject.toml']
|
|
|
144
145
|
exclude_lines = ['NotImplementedError()']
|
|
145
146
|
|
|
146
147
|
[tool.bumpversion]
|
|
147
|
-
current_version = "1.
|
|
148
|
+
current_version = "1.17.0.dev0"
|
|
148
149
|
parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<candidate>\d+))?'
|
|
149
150
|
serialize = [
|
|
150
151
|
'{major}.{minor}.{patch}.{release}{candidate}',
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
|
|
3
|
+
from rdt.errors import InvalidConfigError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _validate_unique_transformer_instances(column_name_to_transformer):
|
|
7
|
+
"""Validate that the transformer instance for each field is unique.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
column_name_to_transformer (dict):
|
|
11
|
+
A dictionary mapping column names to their current transformer.
|
|
12
|
+
|
|
13
|
+
Raises:
|
|
14
|
+
- ``InvalidConfigError`` if transformers in ``column_name_to_transformer`` are repeated.
|
|
15
|
+
"""
|
|
16
|
+
seen_transformers = defaultdict(set)
|
|
17
|
+
for column_name, transformer in column_name_to_transformer.items():
|
|
18
|
+
if transformer is not None:
|
|
19
|
+
seen_transformers[transformer].add(column_name)
|
|
20
|
+
|
|
21
|
+
duplicated_transformers = {
|
|
22
|
+
transformer: columns
|
|
23
|
+
for transformer, columns in seen_transformers.items()
|
|
24
|
+
if len(columns) > 1
|
|
25
|
+
}
|
|
26
|
+
if duplicated_transformers:
|
|
27
|
+
duplicated_column_messages = []
|
|
28
|
+
for duplicated_columns in duplicated_transformers.values():
|
|
29
|
+
columns = ', '.join(
|
|
30
|
+
sorted([
|
|
31
|
+
str(columns) if not isinstance(columns, str) else f"'{columns}'"
|
|
32
|
+
for columns in duplicated_columns
|
|
33
|
+
])
|
|
34
|
+
)
|
|
35
|
+
duplicated_column_messages.append(f'columns ({columns})')
|
|
36
|
+
|
|
37
|
+
if len(duplicated_column_messages) > 1:
|
|
38
|
+
plurality = 'instances are'
|
|
39
|
+
else:
|
|
40
|
+
plurality = 'instance is'
|
|
41
|
+
|
|
42
|
+
error_message = (
|
|
43
|
+
f'The same transformer {plurality} being assigned to '
|
|
44
|
+
f'{", ".join(duplicated_column_messages)}. Please create different transformer objects '
|
|
45
|
+
'for each assignment.'
|
|
46
|
+
)
|
|
47
|
+
raise InvalidConfigError(error_message)
|
|
@@ -8,6 +8,7 @@ from copy import deepcopy
|
|
|
8
8
|
|
|
9
9
|
import pandas as pd
|
|
10
10
|
|
|
11
|
+
from rdt._utils import _validate_unique_transformer_instances
|
|
11
12
|
from rdt.errors import (
|
|
12
13
|
ConfigNotSetError,
|
|
13
14
|
InvalidConfigError,
|
|
@@ -181,6 +182,8 @@ class HyperTransformer:
|
|
|
181
182
|
'Please assign an rdt transformer instance to each column name.'
|
|
182
183
|
)
|
|
183
184
|
|
|
185
|
+
_validate_unique_transformer_instances(column_name_to_transformer)
|
|
186
|
+
|
|
184
187
|
@staticmethod
|
|
185
188
|
def _validate_sdtypes(sdtypes):
|
|
186
189
|
"""Validate the given sdtypes are valid.
|
|
@@ -496,6 +499,33 @@ class HyperTransformer:
|
|
|
496
499
|
if self._fitted:
|
|
497
500
|
warnings.warn(self._REFIT_MESSAGE)
|
|
498
501
|
|
|
502
|
+
def _validate_updated_transformer_unique(self, column_name, transformer):
|
|
503
|
+
"""Validate the transformer being updated is not reused in the config."""
|
|
504
|
+
if (
|
|
505
|
+
transformer in self.field_transformers.values()
|
|
506
|
+
and self.field_transformers.get(column_name) != transformer
|
|
507
|
+
):
|
|
508
|
+
existing_column = [
|
|
509
|
+
column
|
|
510
|
+
for column, existing_transformer in self.field_transformers.items()
|
|
511
|
+
if transformer == existing_transformer
|
|
512
|
+
][0]
|
|
513
|
+
column_name = (
|
|
514
|
+
f"column ('{column_name}')"
|
|
515
|
+
if isinstance(column_name, str)
|
|
516
|
+
else f'columns {str(column_name)}'
|
|
517
|
+
)
|
|
518
|
+
existing_column = (
|
|
519
|
+
f"column ('{existing_column}')"
|
|
520
|
+
if isinstance(existing_column, str)
|
|
521
|
+
else f'columns {str(existing_column)}'
|
|
522
|
+
)
|
|
523
|
+
raise InvalidConfigError(
|
|
524
|
+
f'The transformer for {column_name} is already assigned to '
|
|
525
|
+
f'{existing_column}. Please create different transformer objects for '
|
|
526
|
+
'each assignment.'
|
|
527
|
+
)
|
|
528
|
+
|
|
499
529
|
def update_transformers(self, column_name_to_transformer):
|
|
500
530
|
"""Update any of the transformers assigned to each of the column names.
|
|
501
531
|
|
|
@@ -514,6 +544,9 @@ class HyperTransformer:
|
|
|
514
544
|
self._validate_transformers(column_name_to_transformer)
|
|
515
545
|
|
|
516
546
|
for column_name, transformer in column_name_to_transformer.items():
|
|
547
|
+
if transformer is not None:
|
|
548
|
+
self._validate_updated_transformer_unique(column_name, transformer)
|
|
549
|
+
|
|
517
550
|
columns = column_name if isinstance(column_name, tuple) else (column_name,)
|
|
518
551
|
for column in columns:
|
|
519
552
|
if transformer is not None:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Transformer for datetime data."""
|
|
2
2
|
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
3
5
|
import numpy as np
|
|
4
6
|
import pandas as pd
|
|
5
7
|
from pandas.api.types import is_datetime64_dtype, is_numeric_dtype
|
|
@@ -8,6 +10,7 @@ from pandas.core.tools.datetimes import _guess_datetime_format_for_array
|
|
|
8
10
|
from rdt.errors import TransformerInputError
|
|
9
11
|
from rdt.transformers.base import BaseTransformer
|
|
10
12
|
from rdt.transformers.null import NullTransformer
|
|
13
|
+
from rdt.transformers.utils import _safe_parse_datetime, data_has_multiple_timezones
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
class UnixTimestampEncoder(BaseTransformer):
|
|
@@ -68,41 +71,75 @@ class UnixTimestampEncoder(BaseTransformer):
|
|
|
68
71
|
|
|
69
72
|
self.datetime_format = datetime_format
|
|
70
73
|
self._dtype = None
|
|
74
|
+
self._has_multiple_timezones = False
|
|
75
|
+
self._timezone_offset = None
|
|
76
|
+
|
|
77
|
+
def _warn_if_mixed_timezones(self):
|
|
78
|
+
if self._has_multiple_timezones:
|
|
79
|
+
warnings.warn(
|
|
80
|
+
'Mixed timezones are not supported in SDV Community. Data will be converted to UTC.'
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def _raise_appropriate_conversion_error(self, error):
|
|
84
|
+
message = str(error)
|
|
85
|
+
if 'Unknown string' in message or 'Unknown datetime string' in message:
|
|
86
|
+
raise TypeError('Data must be of dtype datetime, or castable to datetime.') from None
|
|
87
|
+
|
|
88
|
+
raise ValueError('Data does not match specified datetime format.') from None
|
|
89
|
+
|
|
90
|
+
def _learn_timezone_offest(self, data):
|
|
91
|
+
"""Extracts and stores the timezone offset from the first valid datetime in the data."""
|
|
92
|
+
has_timezone = self.datetime_format and '%z' in self.datetime_format.lower()
|
|
93
|
+
if has_timezone and not self._has_multiple_timezones:
|
|
94
|
+
for val in data:
|
|
95
|
+
if pd.notna(val):
|
|
96
|
+
try:
|
|
97
|
+
dt = _safe_parse_datetime(
|
|
98
|
+
str(val), warn=True, datetime_format=self.datetime_format
|
|
99
|
+
)
|
|
100
|
+
self._timezone_offset = dt.tzinfo
|
|
101
|
+
break
|
|
102
|
+
|
|
103
|
+
except (ValueError, TypeError, AttributeError):
|
|
104
|
+
self._timezone_offset = None
|
|
105
|
+
|
|
106
|
+
def _learn_has_multiple_timezones(self, data):
|
|
107
|
+
"""Determines if the data contains multiple timezones and stores the result."""
|
|
108
|
+
if self.datetime_format and '%z' not in self.datetime_format.lower():
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
if not isinstance(data, pd.Series):
|
|
112
|
+
data = data.to_series()
|
|
113
|
+
|
|
114
|
+
self._has_multiple_timezones = data_has_multiple_timezones(
|
|
115
|
+
data, datetime_format=self.datetime_format
|
|
116
|
+
)
|
|
71
117
|
|
|
72
|
-
def
|
|
73
|
-
"""
|
|
118
|
+
def _needs_datetime_conversion(self, data):
|
|
119
|
+
"""Determines if the data requires datetime conversion."""
|
|
120
|
+
return self.datetime_format is not None or not is_numeric_dtype(data)
|
|
74
121
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
122
|
+
def _get_pandas_datetime_format(self):
|
|
123
|
+
"""Converts the instance's datetime format to a pandas-compatible format."""
|
|
124
|
+
if self.datetime_format:
|
|
125
|
+
return self.datetime_format.replace('%#', '%').replace('%-', '%')
|
|
79
126
|
|
|
80
|
-
|
|
81
|
-
data (pandas.Series):
|
|
82
|
-
The datetime column.
|
|
127
|
+
return None
|
|
83
128
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
129
|
+
def _to_datetime(self, data):
|
|
130
|
+
"""Converts data to datetime using the instance's datetime format."""
|
|
131
|
+
return pd.to_datetime(
|
|
132
|
+
data,
|
|
133
|
+
format=self._get_pandas_datetime_format(),
|
|
134
|
+
utc=getattr(self, '_has_multiple_timezones', False), # Backward compatibility
|
|
135
|
+
)
|
|
87
136
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
The datetime column converted to the datetime dtype.
|
|
91
|
-
"""
|
|
92
|
-
if self.datetime_format or not is_numeric_dtype(data):
|
|
137
|
+
def _convert_to_datetime(self, data):
|
|
138
|
+
if self._needs_datetime_conversion(data):
|
|
93
139
|
try:
|
|
94
|
-
|
|
95
|
-
if self.datetime_format:
|
|
96
|
-
pandas_datetime_format = self.datetime_format.replace('%-', '%')
|
|
97
|
-
|
|
98
|
-
data = pd.to_datetime(data, format=pandas_datetime_format)
|
|
99
|
-
|
|
140
|
+
return self._to_datetime(data)
|
|
100
141
|
except ValueError as error:
|
|
101
|
-
|
|
102
|
-
message = 'Data must be of dtype datetime, or castable to datetime.'
|
|
103
|
-
raise TypeError(message) from None
|
|
104
|
-
|
|
105
|
-
raise ValueError('Data does not match specified datetime format.') from None
|
|
142
|
+
self._raise_appropriate_conversion_error(error)
|
|
106
143
|
|
|
107
144
|
return data
|
|
108
145
|
|
|
@@ -116,15 +153,6 @@ class UnixTimestampEncoder(BaseTransformer):
|
|
|
116
153
|
|
|
117
154
|
return transformed
|
|
118
155
|
|
|
119
|
-
def _reverse_transform_helper(self, data):
|
|
120
|
-
"""Transform integer values back into datetimes."""
|
|
121
|
-
if not isinstance(data, np.ndarray):
|
|
122
|
-
data = data.to_numpy()
|
|
123
|
-
|
|
124
|
-
data = self.null_transformer.reverse_transform(data)
|
|
125
|
-
data = np.round(data.astype(np.float64))
|
|
126
|
-
return data
|
|
127
|
-
|
|
128
156
|
def _fit(self, data):
|
|
129
157
|
"""Fit the transformer to the data.
|
|
130
158
|
|
|
@@ -137,7 +165,11 @@ class UnixTimestampEncoder(BaseTransformer):
|
|
|
137
165
|
datetime_array = data[data.notna()].astype(str).to_numpy()
|
|
138
166
|
self.datetime_format = _guess_datetime_format_for_array(datetime_array)
|
|
139
167
|
|
|
168
|
+
self._learn_has_multiple_timezones(data)
|
|
140
169
|
transformed = self._transform_helper(data)
|
|
170
|
+
self._learn_timezone_offest(data)
|
|
171
|
+
self._warn_if_mixed_timezones()
|
|
172
|
+
|
|
141
173
|
if self.enforce_min_max_values:
|
|
142
174
|
self._min_value = transformed.min()
|
|
143
175
|
self._max_value = transformed.max()
|
|
@@ -200,6 +232,46 @@ class UnixTimestampEncoder(BaseTransformer):
|
|
|
200
232
|
data = self._transform_helper(data)
|
|
201
233
|
return self.null_transformer.transform(data)
|
|
202
234
|
|
|
235
|
+
def _convert_data_to_pandas_datetime(self, data):
|
|
236
|
+
"""Converts data to pandas datetime, applying UTC or specific timezone offset if set."""
|
|
237
|
+
if hasattr(self, '_has_multiple_timezones') and self._has_multiple_timezones:
|
|
238
|
+
return pd.to_datetime(data, utc=True)
|
|
239
|
+
|
|
240
|
+
elif hasattr(self, '_timezone_offset') and self._timezone_offset is not None:
|
|
241
|
+
datime_data = pd.to_datetime(data, utc=True)
|
|
242
|
+
return datime_data.dt.tz_convert(self._timezone_offset)
|
|
243
|
+
|
|
244
|
+
return pd.to_datetime(data)
|
|
245
|
+
|
|
246
|
+
def _handle_datetime_formatting(self, datetime_data):
|
|
247
|
+
"""Formats datetime data based on datetime format or converts to numeric if needed."""
|
|
248
|
+
if self.datetime_format:
|
|
249
|
+
return self._format_datetime(datetime_data)
|
|
250
|
+
|
|
251
|
+
elif is_numeric_dtype(self._dtype):
|
|
252
|
+
datetime_data = pd.to_numeric(datetime_data.astype('object'), errors='coerce')
|
|
253
|
+
return datetime_data.astype(self._dtype)
|
|
254
|
+
|
|
255
|
+
return datetime_data
|
|
256
|
+
|
|
257
|
+
def _format_datetime(self, datetime_data):
|
|
258
|
+
"""Formats datetime data to string or datetime using learned datatime format and dtype."""
|
|
259
|
+
if is_datetime64_dtype(self._dtype) and '.%f' not in self.datetime_format:
|
|
260
|
+
return pd.to_datetime(
|
|
261
|
+
datetime_data.dt.strftime(self.datetime_format), format=self.datetime_format
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
return datetime_data.dt.strftime(self.datetime_format).astype(self._dtype)
|
|
265
|
+
|
|
266
|
+
def _reverse_transform_helper(self, data):
|
|
267
|
+
"""Transform integer values back into datetimes."""
|
|
268
|
+
if not isinstance(data, np.ndarray):
|
|
269
|
+
data = data.to_numpy()
|
|
270
|
+
|
|
271
|
+
data = self.null_transformer.reverse_transform(data)
|
|
272
|
+
data = np.round(data.astype(np.float64))
|
|
273
|
+
return data
|
|
274
|
+
|
|
203
275
|
def _reverse_transform(self, data):
|
|
204
276
|
"""Convert float values back to datetimes.
|
|
205
277
|
|
|
@@ -214,19 +286,8 @@ class UnixTimestampEncoder(BaseTransformer):
|
|
|
214
286
|
if self.enforce_min_max_values:
|
|
215
287
|
data = data.clip(self._min_value, self._max_value)
|
|
216
288
|
|
|
217
|
-
datetime_data =
|
|
218
|
-
|
|
219
|
-
if is_datetime64_dtype(self._dtype) and '.%f' not in self.datetime_format:
|
|
220
|
-
datetime_data = pd.to_datetime(
|
|
221
|
-
datetime_data.dt.strftime(self.datetime_format),
|
|
222
|
-
format=self.datetime_format,
|
|
223
|
-
)
|
|
224
|
-
else:
|
|
225
|
-
datetime_data = datetime_data.dt.strftime(self.datetime_format).astype(self._dtype)
|
|
226
|
-
elif is_numeric_dtype(self._dtype):
|
|
227
|
-
datetime_data = pd.to_numeric(datetime_data.astype('object'), errors='coerce')
|
|
228
|
-
datetime_data = datetime_data.astype(self._dtype)
|
|
229
|
-
|
|
289
|
+
datetime_data = self._convert_data_to_pandas_datetime(data)
|
|
290
|
+
datetime_data = self._handle_datetime_formatting(datetime_data)
|
|
230
291
|
return datetime_data
|
|
231
292
|
|
|
232
293
|
|