【问题标题】:How to specify a variable in pandas as ordinal/categorical?如何将 pandas 中的变量指定为序数/分类?
【发布时间】:2015-06-14 05:40:11
【问题描述】:

我正在尝试使用 scikit-learn 在数据集上运行一些机器学习算法。我的数据集有一些类似于类别的特征。就像一个特性是A,它的值1,2,3 指定某物的质量。 1:Upper, 2: Second, 3: Third class。所以它是一个序数变量。

同样,我将具有三个值('London', Zurich', 'New York' 的变量City 重新编码为1,2,3,但对这些值没有特别的偏好。所以现在这是一个名义分类变量。

如何指定算法以将它们视为熊猫中的分类和序数等?与 R 一样,分类变量由 factor(a) 指定,因此不被视为连续值。 pandas/python 中有类似的东西吗?

【问题讨论】:

    标签: python pandas scikit-learn categorical-data


    【解决方案1】:
    【解决方案2】:

    您应该将OneHotEncoder 转换器与分类变量一起使用,并保持序数变量不变:

    >>> import pandas as pd
    >>> from sklearn.preprocessing import OneHotEncoder
    >>> df = pd.DataFrame({'quality': [1, 2, 3], 'city': [3, 2, 1], columns=['quality', 'city']}
    >>> enc = OneHotEncoder(categorical_features=[False, True])
    >>> X = df.values
    >>> enc.fit(X)
    >>> enc.transform(X).todense()
    matrix([[ 0.,  0.,  1.,  1.],
            [ 0.,  1.,  0.,  2.],
            [ 1.,  0.,  0.,  3.]])
    

    【讨论】:

    • 嗨,我过去曾尝试过。那么这种方法是否对我们指定为虚拟变量的所有分类变量进行编码,对吗?有没有办法保持秩序感?就像质量变量 1,2,3 对质量的种类有一定的意义
    • OneHotEncoder 允许您在 categorical_features 参数中指定要哑化的 vars 子集(数组 cols)。这样您就可以保持序数变量不变并保持秩序感。
    • 但是如果你让序数保持不变,你也没有完成任何事情......
    【解决方案3】:

    ...多年后(因为我认为对这些问题的一个很好的解释不仅是为了这个问题,也是为了帮助提醒自己将来)

    有序与名义

    一般来说,我们会将分类变量转换为虚拟变量(或 host of other methodologies),因为它们是名义变量,例如他们对 a > b > c没有感。在 OP 的原始问题中,这将在伦敦、苏黎世、纽约等城市进行。

    名义虚拟变量

    对于此类问题,pandas 提供了 - 迄今为止 - 使用 pandas.get_dummies 的最简单的转换。所以:

    # create a sample of OPs unique values
    series = pandas.Series(
               numpy.random.randint(low=0, high=3, size=100))
    mapper = {0: 'New York', 1: 'London', 2: 'Zurich'}
    nomvar = series.replace(mapper)
    
    # now let's use pandas.get_dummies
    print(
        pandas.get_dummies(series.replace(mpr))
    
    Out[57]:
        London  New York  Zurich
    0        0         0       1
    1        0         1       0
    2        0         1       0
    3        1         0       0
    

    分类变量的序数编码

    但是对于序数变量,用户在使用pandas.factorize时必须谨慎。原因是工程师希望保留映射中的关系,使得 a > b > c

    因此,如果我想在 large > medium > small 处获取一组分类变量并保留它,我需要确保 pandas.factorize 保留该关系。

    # leveraging the variables already created above
    mapper = {0: 'small', 1: 'medium', 2: 'large'}
    ordvar = series.replace(mapper)
    
    print(pandas.factorize(ordvar))
    
    Out[58]:
    (array([0, 1, 1, 2, 1,...  0, 0]),
    Index(['large', 'small', 'medium'], dtype='object'))
    

    事实上,使用pandas.factorize 已经丢失了为了维护序数概念而需要保留的关系。在这种情况下,我使用自己的映射来确保保留序数属性。

    preserved_mapper = {'large':2 , 'medium': 1, 'small': 0}
    ordvar.replace(preserved_mapper)
    print(ordvar.replace(preserved_mapper))
    
    Out[78]:
    0     2
    1     0
    ...
    99    2
    dtype: int64
    

    事实上,通过创建您自己的dict 来映射值,不仅可以保留您想要的序数关系,还可以用作“保持预测算法的内容和映射井井有条”,确保不仅您是否在此过程中没有丢失任何序数信息,而且还存储了每个变量的每个映射的记录。

    ints 转为 sklearn

    最后,OP 谈到将信息传递到scikit-lean 分类器,这意味着ints 是必需的。对于这种情况,如果您的数据中有任何 NaNs,请确保您知道详细信息为 hereastype(int) gotcha

    【讨论】:

    • 我知道这是旧的。但是,您有一个您认为是序数的热门编码变量吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 2019-06-04
    • 2014-06-20
    • 1970-01-01
    • 2022-07-14
    • 2019-08-15
    • 1970-01-01
    相关资源
    最近更新 更多