pst*_*ohn 5 python pandas scikit-learn
是否有一种 pythonic 方法可以将 sklearn 的 StandardScaler 实例链接在一起以独立地按组缩放数据?即,如果我想找到独立缩放 iris 数据集的特征;我可以使用以下代码:
from sklearn.datasets import load_iris
data = load_iris()
df = pd.DataFrame(data['data'], columns=data['feature_names'])
df['class'] = data['target']
means = df.groupby('class').mean()
stds = df.groupby('class').std()
df_rescaled = (
(df.drop(['class'], 1) - means.reindex(df['class']).values) /
stds.reindex(df['class']).values)
Run Code Online (Sandbox Code Playgroud)
在这里,我分别减去均值并除以每个组的标准差。但是它有点难以实现这些手段和标准差,并且基本上复制了StandardScaler当我有一个我想要控制的分类变量时的行为。
有没有更pythonic/sklearn友好的方式来实现这种类型的缩放?
当然,您可以使用任何sklearn操作并将其应用于groupby对象。
首先,一个方便的包装器:
import typing
import pandas as pd
class SklearnWrapper:
def __init__(self, transform: typing.Callable):
self.transform = transform
def __call__(self, df):
transformed = self.transform.fit_transform(df.values)
return pd.DataFrame(transformed, columns=df.columns, index=df.index)
Run Code Online (Sandbox Code Playgroud)
这将应用sklearn您传递给它的任何变换到一个组。
最后简单的用法:
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
data = load_iris()
df = pd.DataFrame(data["data"], columns=data["feature_names"])
df["class"] = data["target"]
df_rescaled = (
df.groupby("class")
.apply(SklearnWrapper(StandardScaler()))
.drop("class", axis="columns")
)
Run Code Online (Sandbox Code Playgroud)
编辑:你几乎可以用SklearnWrapper. 这是为每个组转换和反转此操作的示例(例如,不要覆盖转换对象) - 每次看到新组时只需重新拟合对象(并将其添加到list)。
sklearn's为了更容易使用,我复制了一些功能(您可以通过将适当的传递string给_call_with_function内部方法来使用您想要的任何功能扩展它):
class SklearnWrapper:
def __init__(self, transformation: typing.Callable):
self.transformation = transformation
self._group_transforms = []
# Start with -1 and for each group up the pointer by one
self._pointer = -1
def _call_with_function(self, df: pd.DataFrame, function: str):
# If pointer >= len we are making a new apply, reset _pointer
if self._pointer >= len(self._group_transforms):
self._pointer = -1
self._pointer += 1
return pd.DataFrame(
getattr(self._group_transforms[self._pointer], function)(df.values),
columns=df.columns,
index=df.index,
)
def fit(self, df):
self._group_transforms.append(self.transformation.fit(df.values))
return self
def transform(self, df):
return self._call_with_function(df, "transform")
def fit_transform(self, df):
self.fit(df)
return self.transform(df)
def inverse_transform(self, df):
return self._call_with_function(df, "inverse_transform")
Run Code Online (Sandbox Code Playgroud)
用法(组变换,逆运算并再次应用):
data = load_iris()
df = pd.DataFrame(data["data"], columns=data["feature_names"])
df["class"] = data["target"]
# Create scaler outside the class
scaler = SklearnWrapper(StandardScaler())
# Fit and transform data (holding state)
df_rescaled = df.groupby("class").apply(scaler.fit_transform)
# Inverse the operation
df_inverted = df_rescaled.groupby("class").apply(scaler.inverse_transform)
# Apply transformation once again
df_transformed = (
df_inverted.groupby("class")
.apply(scaler.transform)
.drop("class", axis="columns")
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3083 次 |
| 最近记录: |