数据挖掘课程实验 1:数据预处理

实验 1:数据预处理实验

一、实验目的及要求:

(1) 在学习的过程中,学生需要在教材的基础上搜索相关的文献资料,采用任何数据预处理方法,只要能达到相应的决策目的即视为有效。
(2) 对于研究内容,只要能够为以后的数据挖掘提供准备功能即可,同时对于研究方法也不做具体的限制,但是要能体现出数据预处理的合理性。

二、实验内容:

(1) 研究数据预处理方法。
(2) 编制出数据预处理方法的程序,并基于实例进行实现得出最终实验结果。

三、设备要求

(1) PC 一台。
(2) Python 或 C++或 JAVA 编程软件。

四、原始数据分析

1、数据来源
数据集为自行生成的。
2、脏数据类型
(1)缺失数据
导致数据缺失的原因有很多种,例如系统问题、人为问题等。假如出现了数据缺失情况,为了不影响数据分析结果的准确性,在数据分析时就需要进行补值,或者将空值排除在分析范围之外。
排除空值会减少数据分析的样本总量,这个时候可以选择性地纳入一些平均数、比例随机数等。若系统中还留有缺失数据的相关记录,可以通过系统再次引入,若系统中也没有这些数据记录,就只能通过补录或者直接放弃这部分数据来解决。
(2)重复数据
相同的数据出现多次的情况相对而言更容易处理,因为只需要去除重复数据即可。
(3)错误数据
错误数据一般是因为数据没有按照规定程序进行记录而出现的。对于异常值,可以通过限定区间的方法进行排除;对于格式错误,需要通过系统内部逻辑结构进行查找;对于数据不统一,无法从系统方面去解决,因为它并不属于真正的“错误”,系统并不能判断出天津和tianjin属于同一“事物”,因此只能通过人工干预的方法,做出匹配规则,用规则表去关联原始表。例如,一旦出现tianjin这个数据就直接匹配到天津。
(4)不可用数据
有些数据虽然正确但却无法使用。
五、算法分析
在这里插入图片描述
在这里插入图片描述
新数据加入可能导致最值变化,需要重新定义;
对奇异值(Outlier)非常敏感,因为其直接影响最值。故最值归一化只适用于数据在一个范围内分布而不会出现Outlier的情况。

4、连续值离散化
连续属性离散化(Discretization of Continuous Attributes)是指将连续数据分段为一系列离散化区间,每个区间对应一个属性值。连续属性离散化的主要原因如下:
算法要求,例如分类决策树等基于分类属性的算法;
连续属性离散化的主要方法阐述如下。
无监督离散方法:
等距离散化,即将连续属性划分为若干有限区间,每个区间长度相等。
等频离散化,即将连续属性划分为若干有限区间,每个区间样本数相同。
有监督离散方法:
信息增益法,是一种二分法(bi-partition),核心是以离散前后信息增益最大的点为二分位点。
5、缺失值处理
侦测成本过高、隐私保护、无效数据、信息遗漏等情况都会造成实际应用时数据集属性缺失,因此缺失值处理不可避免。
缺失值处理的主要方式阐述如下:
插值填充,即用已有数据的分布来推测缺失值。例如均值填充(主要针对连续型属性)、众数填充(主要针对离散型属性)、回归填充(基于已有属性值建立回归方程估计缺失值)等。
相似填充,即用和缺失属性样本相似的若干样本推测缺失值。例如热卡填充(Hot Deck Imputation),基于某种相似度度量选择数据集中与之最相似的样本属性代替缺失值;聚类填充,基于聚类分析选择数据集中与之最相似的样本子集进行插值填充。
C4.5方法,直接使用缺失属性样本,用加权方式衡量样本对结果的影响,主要用于决策树算法。

六、实验结果分析

1、实验设置
利用Jupyter Notebook编写python语言进行数据预处理分析。
2、参数设置
针对不同的数据预处理流程采用不同的数据集。
3、实验结果与分析
(1)缺失值处理
查看数据集中的确实值统计结果,结果如图1所示。图中可以看到每个数据是否为缺失值,是的为true,不是为false。
在这里插入图片描述
图1、缺失值统计结果
处理方法1:删除缺失值,结果如图2所示。可以看到缺失值数量为0。
在这里插入图片描述
图2、删除缺失值
处理方法2:填充或替换缺失值,结果如图3所示。
在这里插入图片描述
图3、填充/替换缺失值
处理方法3:缺失值插补,用均值或众数或中位数插补,结果如图4所示。
在这里插入图片描述
图4、缺失值插补
(2)异常值处理
方法一:调用3 原则,查看随机生成的数据集中存在多少异常值,并画出分布图查看异常值的分布情况,结果如图5所示。
在这里插入图片描述
图5、异常值显示
从图中可以看出,存在异常值28条,其在总的数据中的分布情况也是随机的。
方法二:利用箱型图分析,通过箱型图可以很直观的看出数据的离散分布情况,上四分位数与下四分位数的距离越小说明越集中,否则说明越分散,对于上下边缘来说是一样的。然后通过中位数偏向于上四分位数还是下四分位数可以来分析数据分布的偏向。箱形图还有一个优点是相对受异常值的影响比较小,能够准确稳定地描绘出数据的离散分布情况,会比较有利于数据的清洗。结果如图6所示。
在这里插入图片描述
图6、箱型图分析
3、数据标准化和归一化
(1)0-1标准化,对两列随机数,进行归一化,结果如图7所示。
在这里插入图片描述
图7、归一化结果
从图中可以看出数据已经被统一映射到[0,1]区间上。
(2)Z-score标准化,结果如图8所示。
在这里插入图片描述
图8、Z-score标准化
从图中可以看出,所有数据被映射到均值为0,方差为1的分布中,但并不限制在区间内。
4、数据连续属性离散化
方法一:等宽法,将连续属性划分为若干有限区间,每个区间长度相等。结果如图9所示。
在这里插入图片描述
图9、等宽法
方法二:等频法,将连续属性划分为若干有限区间,每个区间样本数相同。结果如图10所示。
在这里插入图片描述
图10、等频法
从图中可以看出根据样本分位数对数据进行面元划分,得到大小基本相等的面元,但并不能保证每个面元含有相同数据个数。层次较为分明。
5、数据冗余
查看数据集中的重复数据,并对重复数据进行删除处理。结果如图11所示。
在这里插入图片描述
图11、数据冗余
6、表与表的连接
调用python中的merge函数,merge函数默认情况下,会按照相同字段的进行连接,其他参数一般用不到,主要只能两两拼接。结果如图12所示。
在这里插入图片描述

图12、表与表连接

七、实验总结

通过本次数据挖掘的预处理实验,了解了数据预处理的方法和主要步骤,依靠在教材的基础上查询网上的资料,学习了相关数据预处理的算法过程,并完成了对数据预处理方法的具体案例实现,基本掌握了数据预处理的主要过程,为未来的数据挖掘提供准备过程。

附:源代码
(1)缺失值处理

import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats

s = pd.Series([12,33,45,23,np.nan,np.nan,66,54,np.nan,99])
df = pd.DataFrame({'value1':[12,33,45,23,np.nan,np.nan,66,54,np.nan,99,190],
                  'value2':['a','b','c','d','e',np.nan,np.nan,'f','g',np.nan,'g']})
#查看缺失值
print(s.isnull())
print(df.isnull().sum())

2、删除缺失值dropna

# 删除缺失值 - dropna
s.dropna(inplace=True)
df1=df[['value1','value2']].dropna()
print(df1.isnull().sum())

3、填充/替换缺失数据 - fillna、replace
#用0来填补缺失值
s.fillna(0,inplace=True)

#用缺失值之前/之后的数填充
df['value1'].fillna(method='pad',inplace=True)
# method参数:
# pad / ffill → 用之前的数据填充 
# backfill / bfill → 用之后的数据填充 
# print(df['value1'])

#替换缺失值
df['value2'].fillna(0,inplace=True)
print(df)

4、缺失值插补(mean,median,mode,ffill,lagrange)

# 缺失值插补
# 分别求出均值/中位数/众数
u = s.mean()     # 均值
me = s.median()  # 中位数
mod = s.mode()   # 众数
print('均值为:%.2f, 中位数为:%.2f' % (u,me))
print('众数为:', mod.tolist())
print('------')


# 用均值填补
s.fillna(u,inplace = True)
print(s)

#用中位数填补
s.fillna(me,inplace = True)
print(s)

#用众数填补
s.fillna(mod,inplace = True)
print(s)

#临近值填补
#用前值插补
s.fillna(method='ffill',inplace=True)

5、异常值处理

import statsmodels as stats
# 异常值分析
# (13σ原则:如果数据服从正态分布,异常值被定义为一组测定值中与平均值的偏差超过3倍的值 → p(|x - μ| > 3σ)0.003

data = pd.Series(np.random.randn(10000)*100)
u = data.mean()  # 计算均值
std = data.std()  # 计算标准差

print('均值为:%.3f,标准差为:%.3f' % (u,std))

#正态性检验
fig=plt.figure(figsize=(10,6))
ax1=fig.add_subplot(2,1,1)

# 绘制数据密度曲线
data.plot(kind = 'kde',grid = True,style = '-k',title = '密度曲线')

ax2=fig.add_subplot(2,1,2)
error=data[np.abs(data-u)>3*std]
data_c=data[np.abs(data-u)<=3*std]
print("异常值共%d条"%(len(error)))

# 筛选出异常值error、剔除异常值之后的数据data_c
plt.scatter(data_c.index,data_c,color = 'k',marker='.',alpha = 0.3)
plt.scatter(error.index,error,color = 'r',marker='.',alpha = 0.5)
plt.xlim([-10,10010])
plt.grid()
# 图表表达

# 异常值分析
# (2)箱型图分析

fig = plt.figure(figsize = (10,6))
ax1 = fig.add_subplot(2,1,1)
color = dict(boxes='DarkGreen', whiskers='DarkOrange', medians='DarkBlue', caps='Gray')
data.plot.box(vert=False, grid = True,color = color,ax = ax1,label = '样本数据')
# 箱型图看数据分布情况
# 以内限为界

s = data.describe()
print(s)
print('------')
# 基本统计量

q1 = s['25%']
q3 = s['75%']
iqr = q3 - q1
mi = q1 - 1.5*iqr
ma = q3 + 1.5*iqr
print('分位差为:%.3f,下限为:%.3f,上限为:%.3f' % (iqr,mi,ma))
print('------')
# 计算分位差

ax2 = fig.add_subplot(2,1,2)
error = data[(data < mi) | (data > ma)]
data_c = data[(data >= mi) & (data <= ma)]
print('异常值共%i条' % len(error))
# 筛选出异常值error、剔除异常值之后的数据data_c

plt.scatter(data_c.index,data_c,color = 'k',marker='.',alpha = 0.3)
plt.scatter(error.index,error,color = 'r',marker='.',alpha = 0.5)
plt.xlim([-10,10010])
plt.grid()
# 图表表达

df = pd.DataFrame({"value1":np.random.rand(10)*20,
                  'value2':np.random.rand(10)*100})

6、数据归一化和标准化
#创建函数,标准化数据
def data_norm(df,*cols):
    df_n = df.copy()
    for col in cols:
        ma = df_n[col].max()
        mi = df_n[col].min()
        df_n[col + '_n'] = (df_n[col] - mi) / (ma - mi)
    return(df_n)
# 创建函数,标准化数据

df_n = data_norm(df,'value1','value2')
print(df_n.head())

# 数据标准化
# (2)Z-score标准化
from  sklearn import preprocessing
df = pd.DataFrame({"value1":np.random.rand(10) * 100,
                  'value2':np.random.rand(10) * 100})
# 创建数据

def data_Znorm(df, *cols):
    df_n = df.copy()
    for col in cols:
        u = df_n[col].mean()
        std = df_n[col].std()
        df_n[col + '_Zn'] = (df_n[col] - u) / std
    return(df_n)
# 创建函数,标准化数据

#或者直接用scale函数
dd=preprocessing.scale(df)


print(dd)
df_z = data_Znorm(df,'value1','value2')
u_z = df_z['value1_Zn'].mean()
std_z = df_z['value1_Zn'].std()
print(df_z)
print('标准化后value1的均值为:%.2f, 标准差为:%.2f' % (u_z, std_z))
# 标准化数据
# 经过处理的数据符合标准正态分布,即均值为0,标准差为1
# 等宽法 → 将数据均匀划分成n等份,每份的间距相等
# cut方法
ages=[20,22,25,27,21,23,37,31,61,45,41,32]
df=pd.DataFrame({'ages':ages})
# 有一组人员年龄数据,希望将这些数据划分为“1825,2635,3660,60以上”几个面元
bins = [18,25,35,60,100]
group_names=['Youth','YoungAdult','MiddleAged','Senior']
cats=pd.cut(ages,bins=bins,labels=group_names)
cut_counts = s.value_counts(sort=False) 
# print(cats.categories, type(cats.categories))
print(cats)

plt.scatter(df.index,df.values)# 什么情况用Z-score标准化:
# 在分类、聚类算法中,需要使用距离来度量相似性的时候,Z-score表现更好

# 等频法 → 以相同数量的记录放进每个区间
# qcut方法
data = np.random.randn(1000)
s = pd.Series(data)
cats=pd.qcut(s,4)# 按四分位数进行切割
print(pd.value_counts(cats))
# qcut → 根据样本分位数对数据进行面元划分,得到大小基本相等的面元,但并不能保证每个面元含有相同数据个数
# 也可以设置自定义的分位数(01之间的数值,包含端点) → pd.qcut(data1,[0,0.1,0.5,0.9,1])

plt.scatter(s.index,s,cmap = 'Greens',c = pd.qcut(data,4).codes)
plt.xlim([0,1000])
plt.grid()
# 用散点图表示,其中颜色按照codes分类
# 注意codes是来自于Categorical对象

数据冗余
import pandas as pd
import numpy as np
test_dict = {'id':[1,2,3,4,5,6,6],'name':['Alice','Bob','Cindy','Eric','Helen','Grace','Grace'],'math':[90,89,99,78,97,93,93],'english':[89,94,80,94,94,90,90]}
df = pd.DataFrame(test_dict)

#查看冗余行
print(df.duplicated())

#删除冗余行
print(df.drop_duplicates(inplace=True))

表与表的连接
import pandas as pd
import numpy as np
test_dict1 = {'id':[1,2,3,4,5,6],'name':['Alice','Bob','Cindy','Eric','Helen','Grace '],'math':[88,89,99,78,97,93],'english':[89,94,80,94,94,90]}
df1 = pd.DataFrame(test_dict1)
test_dict2 = {'id':[1,2,3,4,5,6],'name':['Alice','Bob','Cindy','Eric','Helen','Grace '],'sex':['female','male','female','female','female','female']}
df2 = pd.DataFrame(test_dict2)
df1.merge(df2)
  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Conn_w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值