如何将 pandas 中的变量指定为序数/分类变量?

问题描述 投票:0回答:4

我正在尝试使用 scikit-learn 在数据集上运行一些机器学习算法。我的数据集有一些类似于类别的特征。就像一个特征是

A
,它的值
1,2,3
指定了某物的质量。
1:Upper, 2: Second, 3: Third class
。所以它是一个序数变量。

类似地,我重新编码了一个变量

City
,将三个值
('London', Zurich', 'New York'
变为
1,2,3
,但对这些值没有特定的偏好。所以现在这是一个名义分类变量。

如何指定算法将这些视为熊猫中的分类和序数等?与 R 中一样,分类变量由

factor(a)
指定,因此不被视为连续值。 pandas/python 中有类似的东西吗?

python pandas scikit-learn categorical-data nominal-data
4个回答
38
投票

...几年后(因为我认为对这些问题的一个很好的解释不仅需要解决这个问题,而且可以帮助将来提醒自己)

序数与名义

一般来说,人们会将分类变量转换为虚拟变量(或一系列其他方法论),因为它们是名义上的,例如他们没有 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

来映射值不仅可以保留您想要的序数关系,而且还可以用作“保持预测算法的内容和映射组织有序”,确保您不仅可以在此过程中没有丢失任何序数信息,而且还存储了每个变量的每个映射的记录。

int

变成
sklearn

最后,OP 谈到将信息传递到 
scikit-lean
 分类器,这意味着 
int

是必需的。对于这种情况,如果您的数据中有任何

astype(int)

,请确保您了解
NaN
的陷阱,详细信息见
此处
您应该将 
OneHotEncoder

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

1
投票
>>> 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.]])

参见
https://pandas.pydata.org/pandas-docs/stable/ generated/pandas.factorize.html
并查看这个问题

1
投票

pd.Categorical()

允许您为(pandas)数据帧创建分类列。对于序数分类数据,传递参数

0
投票

最小工作示例:

import pandas as pd

df = pd.DataFrame(
    {'one': ['d','d','a','c'],
     'two': ['b','d','b','a']
    })
df['one'] = pd.Categorical(df['one'],categories=list('abcd'), ordered=True)
df['two'] = pd.Categorical(df['one'],categories=list('abcd'), ordered=True)

In [1]: df
Out[1]: 
  one two
0   d   b
1   d   d
2   a   b
3   c   a

In [2]: df.dtypes
Out[2]: 
one    category
two    category
dtype: object

这允许您表示类似于 R 的序数数据。


© www.soinside.com 2019 - 2024. All rights reserved.