数据分析-pandas数据预处理.转换数据

一、哑变量处理类别型数据

数据分析模型中有相当一部分的算法模型都要求输入的特征为数值型,但是实际过程中,数据类型不仅是数值型,还会有部分类别型数据参杂其中,此时针对这部分类别型数据采用哑变量处理,让数据适用于所需模型。

get_dummies()

pandas.get_dummies(data,perfix=None,perfix_sep='_',dummy_na=False,columns=None,sparse=False,drop_first=False)

在这里插入图片描述

import pandas as pd
import numpy as np

# 读取数据
detail = pd.read_csv('data/detail.csv',encoding='gbk')

# 哑变量处理
data = pd.get_dummies(detail['dishes_name'])
data.to_csv('data/dishes_name_getdummies.csv',sep=',',index=True)

print('进行哑变量处理前的数据样式:\n',detail['dishes_name'][0:5])
print('进行哑变量处理后的数据样式:\n',data.iloc[:5,:4])

在这里插入图片描述
使用哑变量处理数据后,得到的就是一张关于dishes_name的计数表,例如:0—蒜蓉生蚝,就在第一行找到蒜蓉生蚝列,对应计数1;1—蒙古烤羊腿,在第二行对应蒙古烤羊腿列下计数1;3—芝麻烤紫菜,在第三行对应芝麻烤紫菜下计数1…
简单地说,对于一个类别型特征,若其取值有m个,经过哑变量处理后就会变成m个二元特征,且相互独立,每次只有一个激活(每行计数一个具体类别),此时数据变成了稀疏的矩阵形式,也加快了算法模型的运算速度。
在这里插入图片描述

返回顶部


二、离散化连续型数据

在某些模型算法,特别是分类算法例如:ID3决策算法、Apriori算法等,要求数据为离散型,此时就需要将连续型特征(数值型)变换成离散型特征(类别型),即连续特征离散化。

连续特征的离散化就是在数据的范围内设定若干个离散的划分点,将取值范围划分为一些离散化的区间,最后用不同的符号或者整数值代表落在每个子区间中的数据值。(首先确定分类数,其次将连续型数据映射到类别型数据上).

2.1 等宽法

将数据的值域分为具有相等宽度的区间,区间的个数由数据本身的特点或由用户决定。使用cut函数可以进行连续型数据的等宽离散化。

pandas.cut(x,bins,right=True,labels=None,retbins=False,percision=3,include_lowest=False)
参数名称 说明
x 代表需要进行离散化处理的数据
bins int代表离散化处理后数据的类别数目;序列型表示进行切分的区间,每两个数的间隔为一个区间。
right 代表右边是否为闭区间
labels 代表离散化后各个类别的名称
retbins 代表是否返回区间标签
percision 显示标签的精度
price = pd.cut(detail['amounts'],5)
print('离散化后5条记录售价分布为:\n',price.value_counts())

离散化后5条记录售价分布为:
 (0.823, 36.4]     5461
(36.4, 71.8]      3157
(71.8, 107.2]      839
(142.6, 178.0]     426
(107.2, 142.6]     154
Name: amounts, dtype: int64

使用等宽法虽然可以将其归到一定的区间中,但是当数据分布不均匀的时候,各个类中的数目也会变得非常不均匀,有些区间包含许多的数据,而有的区间数据很少,后期会对建立的模型有所影响。

返回顶部


2.2 等频法

所谓的等频法就是通过定义将相同数量的数据(记录)放进每个区间。

# 自定义等频法离散化数据
def sameratecut(data,k):
    w = data.quantile(np.arange(0,1+1.0/k,1.0/k))
    data = pd.cut(data,w)
    return data
# 对菜品售价进行等频法离散化数据
result = sameratecut(detail['amounts'],5).value_counts()
print('菜品数据等频法离散化数据后各个类别数目分布情况:\n',result) 

菜品数据等频法离散化数据后各个类别数目分布情况:
 (18.0, 32.0]     2107
(39.0, 58.0]     2080
(32.0, 39.0]     1910
(1.0, 18.0]      1891
(58.0, 178.0]    1863
Name: amounts, dtype: int64

在定义等频法是关键的方法是使用到了quantile(),才使得每个区间中的数目相对平均。以下对其进行拆分逐步分析:

在这里插入图片描述

# 区间端点值
print(detail['amounts'].max())
print(detail['amounts'].min())
178
1

这里准确来讲并不是真正的四分位数,我只是借此来表明此处的数值与四分位数作用相同,表示数据中的占比20%、40%、60%、80%,其默认为0.5(50%)。

# 要传入计算的四分位数
m = np.arange(0,1+1.0/5,1.0/5)
print(m)
[0.  0.2 0.4 0.6 0.8 1. ]
# 返回四分位数对应的值
w = detail['amounts'].quantile(np.arange(0,1+1.0/5,1.0/5))
print(w)

0.0      1.0
0.2     18.0
0.4     32.0
0.6     39.0
0.8     58.0
1.0    178.0
Name: amounts, dtype: float64

返回顶部


2.3 聚类分析法

一维聚类的方法包括两个步骤:

  • 首先将连续型数据用聚类算法进行聚类
  • 然后处理聚类得到的簇,为合并到一个簇的连续型数据做同一种标记
    (聚类分析的离散化方法需要用户指定簇的个数,用来决定产生的区间数。)
# 自定义数据K-Means聚类离散化函数
def kmeancut(data,k):
    from sklearn.cluster import KMeans
    # 建立模型
    kmodel = KMeans(n_clusters=k)
    # 训练模型
    kmodel.fit(data.values.reshape((len(data),1)))
    # 输出聚类中心并排序
    c = pd.DataFrame(kmodel.cluster_centers_).sort_values(0)
    # 相邻两项求中点,作为边界点
    w = c.rolling(2).mean().iloc[1:]
    # 把末边界点加上
    w = [0]+list(w[0])+[data.max()]
    data = pd.cut(data,w)
    return data

# 菜品售价等频法离散化
result=kmeancut(detail['amounts'],5).value_counts()
print('菜品售价聚类离散化后各个类别数目分布状况为:\n',result)

菜品售价聚类离散化后各个类别数目分布状况为:
 (22.31, 43.51]       3690
(43.51, 73.945]      2474
(0.0, 22.31]         2454
(73.945, 131.858]     993
(131.858, 178.0]      426
Name: amounts, dtype: int64

分步拆解

设置并计算要形成的团簇数目以及要生成的质心数。

kmodel = KMeans(n_clusters=5)  
print(kmodel)
# KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
#       n_clusters=5, n_init=10, n_jobs=None, precompute_distances='auto',
#       random_state=None, tol=0.0001, verbose=0)


kmodel1= kmodel.fit(detail['amounts'].values.reshape((len(detail['amounts']),1)))
print(kmodel1)
# KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
#       n_clusters=5, n_init=10, n_jobs=None, precompute_distances='auto',
#       random_state=None, tol=0.0001, verbose=0)

输出聚类中心并排序,也就是之后传入k=5时,分为5个簇,找出每个簇的中心点。

c = pd.DataFrame(kmodel.cluster_centers_).sort_values(0)
print(c)
#            0
#4   12.179707
#1   32.439295
#3   54.580437
#0   93.310171
#2  170.406103

计算相邻中心点的中点值作为边界点,同时加上始末、点,便于构成完整的区间。

# 相邻两项求中点,作为边界点
w = c.rolling(2).mean().iloc[1:]
print(w)
# 把末边界点加上
w = [0]+list(w[0])+[m]
print(w)
#            0
#1   22.309501
#3   43.509866
#0   73.945304
#2  131.858137
#[0, 22.30950099721165, 43.50986596648579, 73.9453038692032, 131.85813724238798, 178]

使用cut函数离散化数据,其中参数bins传入的是序列型数据w,则表示进行切分的区间。

data = pd.cut(detail['amounts'],w)
print(data)
#0        (43.51, 73.945]
#1        (43.51, 73.945]
#2         (22.31, 43.51]
#3         (22.31, 43.51]
#4           (0.0, 22.31]
              ...       
#10032     (22.31, 43.51]
#10033     (22.31, 43.51]
#10034     (22.31, 43.51]
#10035       (0.0, 22.31]
#10036     (22.31, 43.51]
#Name: amounts, Length: 10037, dtype: category
#Categories (5, interval[float64]): [(0.0, 22.31] < (22.31, 43.51] < (43.51, 73.945] < (73.945, 131.858] < (131.858, 178.0]]

最后使用.value_counts()进行频数统计。

result=kmeancut(detail['amounts'],5).value_counts()
print('菜品售价聚类离散化后各个类别数目分布状况为:\n',result)

#菜品售价聚类离散化后各个类别数目分布状况为:
# (22.31, 43.51]       3690
#(43.51, 73.945]      2474
#(0.0, 22.31]         2454
#(73.945, 131.858]     993
#(131.858, 178.0]      426
#Name: amounts, dtype: int64

返回顶部


Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐