pandas 转换为文本类型_pandas文本数据转整数分类编码的最佳实践

本文探讨了如何使用pandas和scikit-learn将包含分类变量的数据集转换为数值编码,以便于分析。通过示例介绍了替换字符串、标签编码、one-hot编码和自定义二分类等方法,以及它们的优缺点。文中使用了一个包含汽车数据的UCI数据集进行演示。
摘要由CSDN通过智能技术生成

问题描述

在许多实际的数据处理工作中,数据集通常包含分类变量。这些变量通常存储为表示各种特征的文本值。一些示例包括颜色(“红色”,“黄色”,“蓝色”),尺寸(“小”,“中”,“大”)或地理名称(州或国家)。无论使用何种值,挑战在于确定如何在分析中使用此数据。许多机器学习算法可以支持分类值而无需进一步操作,但还有许多算法不支持。因此,分析师面临的挑战是如何将这些文本属性转换为数值以便进一步处理。

与数据科学世界的许多其他方面一样,关于如何解决这个问题没有单一的答案。每种方法都需要权衡,并对分析结果产生潜在影响。幸运的是,pandas和scikit-learn的python工具提供了几种方法,可用于将分类数据转换为合适的数值。本文将对一些常见的(以及一些更复杂的)方法进行汇总,希望它能帮助其他人将这些技术应用于他们的现实世界问题。

数据集

在本文中,我在UCI机器学习库中找到一个好的数据集。这个特定的汽车数据集包括分类值和连续值的组合,并且作为相对容易理解的有用示例。由于在决定如何编码各种分类值时,领域知识是一个重要方面 - 这个数据集是一个很好的个案研究。

在我们开始编码各种值之前,我们需要载入数据并进行一些小的清理。幸运的是,pandas使这简单明了:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15import pandas as pd

import numpy as np

# 定义数据的列名称, 因为这个数据集没有包含列名称

headers = ["symboling", "normalized_losses", "make", "fuel_type", "aspiration",

"num_doors", "body_style", "drive_wheels", "engine_location",

"wheel_base", "length", "width", "height", "curb_weight",

"engine_type", "num_cylinders", "engine_size", "fuel_system",

"bore", "stroke", "compression_ratio", "horsepower", "peak_rpm",

"city_mpg", "highway_mpg", "price"]

# 读取在线的数据集, 并将?转换为缺失NaN

df = pd.read_csv("http://mlr.cs.umass.edu/ml/machine-learning-databases/autos/imports-85.data",

header=None, names=headers, na_values="?" )

df.head()[df.columns[:10]]

输出(html):

symboling

normalized_losses

make

fuel_type

aspiration

num_doors

body_style

drive_wheels

engine_location

wheel_base

0

3

NaN

alfa-romero

gas

std

two

convertible

rwd

front

88.6

1

3

NaN

alfa-romero

gas

std

two

convertible

rwd

front

88.6

2

1

NaN

alfa-romero

gas

std

two

hatchback

rwd

front

94.5

3

2

164.0

audi

gas

std

four

sedan

fwd

front

99.8

4

2

164.0

audi

gas

std

four

sedan

4wd

front

99.4

看一下所有列的数据类型:

1df.dtypes

输出(plain):

symboling int64

normalized_losses float64

make object

fuel_type object

aspiration object

num_doors object

body_style object

drive_wheels object

engine_location object

wheel_base float64

length float64

width float64

height float64

curb_weight int64

engine_type object

num_cylinders object

engine_size int64

fuel_system object

bore float64

stroke float64

compression_ratio float64

horsepower float64

peak_rpm float64

city_mpg int64

highway_mpg int64

price float64

dtype: object

因为我们只关心文本数据, 所以我们选出类型为”object”的列, 而pandas提供了select_dtypes方法可以快速达到目的:

1

2df2 = df.select_dtypes('object').copy()

df2.head()

输出(html):

make

fuel_type

aspiration

num_doors

body_style

drive_wheels

engine_location

engine_type

num_cylinders

fuel_system

0

alfa-romero

gas

std

two

convertible

rwd

front

dohc

four

mpfi

1

alfa-romero

gas

std

two

convertible

rwd

front

dohc

four

mpfi

2

alfa-romero

gas

std

two

hatchback

rwd

front

ohcv

six

mpfi

3

audi

gas

std

four

sedan

fwd

front

ohc

four

mpfi

4

audi

gas

std

four

sedan

4wd

front

ohc

five

mpfi

因为数据集种包括缺失数据, 这会增加后续处理的难度, 我们为了简单起见, 将缺失值删除即可:

1df2.dropna(inplace=True)

方案Ⅰ:替换字符串

最简单的方式就是, 查找列中所有的字符串, 然后给不同的字符串一个编号, 然后用编号替换字符串:

使用vlaue_counts获取所有的字符串:

1

2

3

4col = 'body_style'

strs = df2[col].value_counts()

strs

输出(plain):

sedan 94

hatchback 70

wagon 25

hardtop 8

convertible 6

Name: body_style, dtype: int64

将所有字符串映射为数字:

1

2value_map = dict((v, i) for i,v in enumerate(strs.index))

value_map

输出(plain):

{'sedan': 0, 'hatchback': 1, 'wagon': 2, 'hardtop': 3, 'convertible': 4}

使用replace方法替换字符串

1df2.replace({col:value_map})[col].head()

输出(plain):

0 4

1 4

2 1

3 0

4 0

Name: body_style, dtype: int64

你会看到, 不仅仅字符串被替换, 而且series的数据类型变成了int64

方案Ⅱ:标签编码

编码分类值的另一种方法是使用称为标签编码的技术。标签编码只是将列中的每个值转换为数字。例如,body_style列包含5个不同的值。我们可以选择像这样编码:

convertible -> 0

hardtop -> 1

hatchback -> 2

sedan -> 3

wagon -> 4

首先你可以将列的数据格式转换为category

1

2bs = df2['body_style'].astype('category')

bs.head()

输出(plain):

0 convertible

1 convertible

2 hatchback

3 sedan

4 sedan

Name: body_style, dtype: category

Categories (5, object): [convertible, hardtop, hatchback, sedan, wagon]

然后你只需要使用标签的编码作为真正的数据就可以了:

1bs.cat.codes.head()

输出(plain):

0 0

1 0

2 2

3 3

4 3

dtype: int8

方案三: 转换成哑变量, 或者叫one-hot编码

标签编码的优点是它很简单,但它的缺点是数值可能被算法“误解”。例如,0的值显然小于4的值,但这是否真的与现实生活中的数据集相对应?在我们的计算中,旅行车的重量是否比敞篷车重4倍?在这个例子中,我不这么认为。所以我们需要将数据转换为哑变量(onehot), 在pandas中, 这个转变只需要一行代码:

1pd.get_dummies(df[['drive_wheels', 'body_style']]).head()

输出(html):

drive_wheels_4wd

drive_wheels_fwd

drive_wheels_rwd

body_style_convertible

body_style_hardtop

body_style_hatchback

body_style_sedan

body_style_wagon

0

0

0

1

1

0

0

0

0

1

0

0

1

1

0

0

0

0

2

0

0

1

0

0

1

0

0

3

0

1

0

0

0

0

1

0

4

1

0

0

0

0

0

1

0

方案四: 自定义二分类

根据数据集,您可以使用标签编码和one-hot来创建满足进一步分析需求的二分类列

在此特定数据集中,有一个名为engine_type的列包含几个不同的值:

1df2['engine_type'].value_counts()

输出(plain):

ohc 146

ohcf 15

ohcv 13

dohc 12

l 12

rotor 4

dohcv 1

Name: engine_type, dtype: int64

为了便于讨论,我们可能关心的是发动机是否是顶置凸轮(OHC)。换句话说,OHC的各种版本对于该分析都是相同的。如果是这种情况,那么我们可以使用str accessor创建一个新列,指示汽车是否有OHC引擎。

1df2["engine_type"].str.contains("ohc").map(int).value_counts()

输出(plain):

1 187

0 16

Name: engine_type, dtype: int64

Scikit-Learn

除了pandas方法,scikit-learn还提供类似的功能。就个人而言,我发现使用pandas有点简单,但我认为重要的是要知道如何在scikit-learn中执行这些过程。

例如,如果我们想对汽车的品牌进行标签编码,我们需要实例化LabelEncoder对象并fit_transform数据:

1

2

3

4

5from sklearn.preprocessing import LabelBinarizer

lb_style = LabelBinarizer()

lb_results = lb_style.fit_transform(df2["body_style"])

pd.DataFrame(lb_results, columns=lb_style.classes_).head()

输出(html):

convertible

hardtop

hatchback

sedan

wagon

0

1

0

0

0

0

1

1

0

0

0

0

2

0

0

1

0

0

3

0

0

0

1

0

4

0

0

0

1

0

注意

本文由jupyter notebook转换而来, 您可以在这里下载notebook

有问题可以直接在下方留言

或者给我发邮件675495787[at]qq.com

请记住我的网址: mlln.cn 或者 jupyter.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值