pandas数据分割pd.cut使用总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pandas数据分割pd.cut使用总结相关的知识,希望对你有一定的参考价值。
参考技术A pandas.cut用来把一组数据分割成离散的区间。比如有一组年龄数据,可以使用pandas.cut将年龄数据分割成不同的年龄段并打上标签。参数含义
x: 被切分的类数组(array-like)数据,必须是1维的(不能用DataFrame);
bins :bins是被切割后的区间(或者叫“桶”、“箱”、“面元”),有3中形式:一个int型的标量、标量序列(数组)或者pandas.IntervalIndex 。
一个int型的标量——当bins为一个int型的标量时,代表将x平分成bins份。x的范围在每侧扩展0.1%,以包括x的最大值和最小值。
标量序列 —— 标量序列定义了被分割后每一个bin的区间边缘,此时x没有扩展。
pandas.IntervalIndex ——定义要使用的精确区间。
right :bool型参数,默认为True,表示是否包含区间右部。比如如果bins=[1,2,3],right=True,则区间为(1,2],(2,3];right=False,则区间为(1,2),(2,3)。
labels :给分割后的bins打标签,比如把年龄x分割成年龄段bins后,可以给年龄段打上诸如青年、中年的标签。labels的长度必须和划分后的区间长度相等,比如bins=[1,2,3],划分后有2个区间(1,2],(2,3],则labels的长度必须为2。如果指定labels=False,则返回x中的数据在第几个bin中(从0开始)。
retbins :bool型的参数,表示是否将分割后的bins返回,当bins为一个int型的标量时比较有用,这样可以得到划分后的区间,默认为False。
precision :保留区间小数点的位数,默认为3.
include_lowest :bool型的参数,表示区间的左边是开还是闭的,默认为false,也就是不包含区间左部(闭)。
duplicates :是否允许重复区间。有两种选择:raise:不允许,drop:允许。
out :一个pandas.Categorical, Series或者ndarray类型的值,代表分区后x中的每个值在哪个bin(区间)中,如果指定了labels,则返回对应的label。
bins :分隔后的区间,当指定retbins为True时返回。
🌰:这里拿给年龄分组当做例子。
参考: pandas.cut使用总结 - ColdCode - 博客园
有没有办法在 sklearn 管道中链接 pd.cut FunctionTransformer?
【中文标题】有没有办法在 sklearn 管道中链接 pd.cut FunctionTransformer?【英文标题】:Is there a way to chain a pd.cut FunctionTransformer in a sklearn Pipeline? 【发布时间】:2020-10-07 22:23:07 【问题描述】:我正在使用 sklearn 制作 DataFrame 预处理管道并链接各种类型的预处理步骤。
我想链接 SimpleImputer
变压器和 FunctionTransformer
应用 pd.qcut
(或 pd.cut
),但我不断收到以下错误:
ValueError: 输入数组必须是一维的
这是我的代码:
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import FunctionTransformer
class FeatureSelector(BaseEstimator, TransformerMixin):
def __init__(self, features):
self._features = features
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
return X[self._features]
fare_transformer = Pipeline([
('fare_selector', FeatureSelector(['Fare'])),
('fare_imputer', SimpleImputer(strategy='median')),
('fare_bands', FunctionTransformer(func=pd.qcut, kw_args='q': 5))
])
如果我简单地将FeatureSelector
转换器和FunctionTransformer
与pd.qcut
链接并省略SimpleImputer
,也会发生同样的情况:
fare_transformer = Pipeline([
('fare_selector', FeatureSelector(['Fare'])),
('fare_bands', FunctionTransformer(func=pd.qcut, kw_args='q': 5))
])
我广泛搜索了 *** 和 google,但找不到解决此问题的方法。在这里的任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:sklearn 已经有这样的转换器,KBinsDiscretizer
(匹配pd.qcut
,使用strategy='quantile'
)。它的主要区别在于transform
s 测试数据的方式:FunctionTransformer
版本将“重新调整”分位数,而内置的KBinsDiscretizer
将保存分位数统计信息以对测试数据进行分箱。正如@m_power 在评论中指出的那样,它们在 bin 边缘附近以及转换后数据的格式也有所不同。
但要具体解决该错误:这意味着您的函数 qcut
仅适用于一维数组,而 FunctionTransformer
发送整个数据帧。您可以在 qcut
周围定义一个薄包装器来完成这项工作,例如
def frame_qcut(X, y=None, q=10):
return X.apply(pd.qcut, axis=0, q=q)
(假设您将获得一个数据框。)
【讨论】:
感谢您的及时回复。通过使用 FeatureSelector 从我的 DataFrame 中选择“Fare”列,我以为我正在为 FunctionTransformer 提供一个应该与 pd.qcut 一起使用的熊猫系列,例如pd.qcut(df['Fare'], q=5) @LazyEval 在管道中的FeatureSelector
参数中将['Fare']
替换为'Fare'
将以这种方式工作:X[['Fare']]
是一个数据框,但X['Fare']
是一个系列,这将在qcut
工作。这适用于您的第二个更简单的管道,但会在第一个中失败,因为现在 SimpleImputer
将抱怨一维输入。
哦,好吧,我什至没有真正想过 X['Fare'] 和 X[['Fare']] 之间的区别......我傻了。谢谢!
当应用于一个简单的一维数组(例如np.random.rand(10,1)
)时,quantile
KBinsDiscretizer
和 pd.qcut
没有得到相同的结果。根据您的说法,两种解决方案应该是相同的。
@m_power,数学内容是一样的(虽然我可以理解由于插值造成的细微差异,但我在你这样的随机示例中没有发现任何差异),只是格式不同。 KBinsDiscretizer
的 bin_edges_
匹配 qcut
的第二个可选输出 bins
随机示例。 qcut
将输出作为间隔返回,而KBinsDiscretizer
将编码返回为 one-hot 或 ordinal。以上是关于pandas数据分割pd.cut使用总结的主要内容,如果未能解决你的问题,请参考以下文章