I'm writing a extension for sklearn preprocessing. I have problem to write a 'inplace' version of the method you would typically see in many pandas methods. So my methods can either return a new df or change the input df directly.
class OneHotEncoder(preprocessing.OneHotEncoder):
"""
Parameters
----------
categories : 'auto' or a list of array-like, default='auto'
Categories (unique values) per feature:
- 'auto' : Determine categories automatically from the training data.
- list : ``categories[i]`` holds the categories expected in the ith
I'm saving a lot of description here
"""
# @_deprecate_positional_args
def __init__(self, n_values=None, categorical_features=None,
categories=None, drop=None, sparse=True, dtype=np.float64,
handle_unknown='error'):
super().__init__(n_values, categorical_features, categories, drop, sparse, dtype, handle_unknown)
def encode(self, X, columns, inplace: bool = False):
"""Encode categorical features as a pandas dataframe.
Parameters
----------
X : pandas dataframe.
columns : a list of str.
Indicate which columns you wish to encode.
inplace : bool, default False
If True, do operation inplace and return None.
Return
----------
encoded_X : One-hot encoded dataframe if inplace=False
"""
new_data = X.copy()
if not isinstance(columns, collections.Sequence):
raise TypeError("Input must be a sequence-like parameter 'columns'")
if len(columns) == 0:
raise ValueError("Input must not be empty parameter 'columns'")
if isinstance(X, pd.DataFrame):
encoded_n_array = super().fit_transform(new_data.loc[:, columns]).astype(self.dtype).toarray()
# categories_dict = dict(zip(columns, self.categories_))
col_names = []
for i, column in enumerate(columns):
num_categories = len(self.categories_[i])
if self.drop == 'first':
# If only one category is present, the feature will be dropped entirely.
if num_categories != 1:
num_categories = len(self.categories_[i]) - 1
col_names.append(np.char.add(np.repeat(column + '_', num_categories), self.categories_[i][1:]))
else:
continue
elif self.drop == 'if_binary' and num_categories == 2:
col_names.append(np.array([column + '' + self.categories_[0][1]]))
else:
col_names.append(np.char.add(np.repeat(column + '_', num_categories), self.categories_[i]))
col_names = np.concatenate(col_names, axis=0)
encoded_df = pd.DataFrame(encoded_n_array, columns=col_names)
new_data = pd.concat([new_data, encoded_df], axis=1)
new_data = new_data.drop(columns=columns)
if inplace:
X = new_data ################ here the inplace does change anything.
else:
return new_data
else:
raise TypeError("Input must be a DataFrame parameter 'X'")
Basically I'm inputting a X to the encode method. I want to be able to change input X inplace or just return a new copy. I changed X copy new_data for many times. But unable to change X inplace. I know my way is wrong. But how to change it? Thank you.