数据处理(一):数据质量分析
- 导入数据
- 空值分析
- 异常值分析
- 数据特征分析
数据质量分析是数据挖掘中数据准备过程中的重要一环,是数据预处理的前提,也是数据挖掘分析结论有效性和准确性的基础。数据质量分析主要任务是检查原始数据中是否存在脏数据,脏数据指的是不符合要求,以及不能直接进行分析的数据。常见的脏数据包括如下:
1.缺失值
2.异常值
3.不一致的值
4.重复数据及含有特殊符号(如#,¥,*)的数据
这里我用比赛的数据来做实验:
数据保存在网盘:链接: https://pan.baidu.com/s/1SD2MPupiRloQFv2kBxyAUA 提取码: 58e1
欢迎大家下载。建议大家多动手绘制绘制。
第一步:导入库和数据
这里我们定义一个类来管理数据:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
import numpy as np
warnings.filterwarnings('ignore') #忽略警告
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
class PrePross(object):
def __init__(self, url):
self.data = pd.DataFrame(pd.read_csv(url)) #打开文件,读取数据
if __name__ == '__main__':
url = r'movies_metadata.csv'
data = PrePross(url)
第二步:缺失值分析
数据缺失主要包括记录的缺失和记录某个字段信息的缺失,两个都会造成分析误差。我们简单地分析以下缺失值的原因,影响。
2.1 缺失值产生的原因
- 有些数据暂时无法获取,或者获取信息代价太大
- 有些信息被遗漏,忘记填写,或者数据采集设备出错
- 属性值不存在。比如:儿童的固定收入
2.2 缺失值的影响
- 数据挖掘建模将丢失大量有用数据
- 不确定性更加显著,规律更难把握
- 使建模过程出现混乱,导致不可靠的输出
2.3 缺失值分析
使用简单的统计分析,可以得到含有缺失值的属性的个数,以及每个属性的未缺失数,缺失数与缺失率等。代码如下:
def missVal(self, col=None): #我们在类中添加如下代码
raw, column = self.data.shape
if col:
num = self.data[col].isnull().sum().sort_values()
else:
num = self.data.isnull().sum().sort_values()
print(col, r"缺失数", num)
print(col, r'缺失比例', num/raw)
if __name__ == '__main__':
url = r'movies_metadata.csv'
data = PrePross(url)
data.missVal()
我们看到输出如下:
数据 | 缺失数 | 缺失率 |
---|---|---|
adult | 0 | 0.000000 |
budget | 0 | 0.000000 |
genres | 0 | 0.000000 |
id | 0 | 0.000000 |
original_title | 0 | 0.000000 |
production_countries | 3 | 0.000066 |
production_companies | 3 | 0.000066 |
… | … | … |
poster_path | 386 | 0.008490 |
overview | 954 | 0.020983 |
tagline | 25054 | 0.551049 |
homepage | 37684 | 0.828839 |
belongs_to_collection | 40972 | 0.901157 |
第三部:异常值分析
异常值也被称作离群点,异常值分析也称为离群点分析。主要有三种方法
3.1 简单统计分析
先对变量做一个描述性统计。常用的统计量是最大值和最小值,判断是否超出了合理的范围。
3.2 3σ原则
前提:数据服从正太分布
在正太分布的假设下,距离平均值3σ之外的值出现的概率为P<=0.003,属于小概率事件,被称为异常值
代码如下:
def abnorVal1(self,col): #利用3sigma原则
col2 = self.data.shape[0]
u = self.data[col].mean()
std = self.data[col].std()
stats.kstest(self.data[col], 'norm', (u, std))
print('均值为: %.3f. 标准差为: %.3f' %(u, std))
#正太性检验
flg = plt.figure(figsize=(10, 6))
ax1 = flg.add_subplot(2,1,1)
self.data[col].plot(kind = 'kde', grid = True, style = '-k', title = '密度曲线')
plt.axvline(3*std, color='r', linestyle="--", alpha = 0.8)
plt.axvline(-3*std, color='r', linestyle="--", alpha = 0.8)
#绘制数据密度曲线
ax2 = flg.add_subplot(2,1 ,2)
error = self.data[col][np.abs(self.data[col] - u) > 3*std]
data_c = self.data[col][np.abs(self.data[col] - u) < -3*std]
print('异常值共%d条' % len(error))
print('异常值出现的概率%.4f' % (len(error)/col2))
plt.scatter(data_c.index, data_c, color='k', marker='.', alpha=0.3)
plt.scatter(error.index, error, color = 'r', marker='.', alpha=0.3)
plt.xlim([-10,10010])
plt.grid()
plt.show()
if __name__ == '__main__':
url = r'movies_metadata.csv'
data = PrePross(url)
data.abnorVal1('runtime')
输出如下:
均值为: 94.128. 标准差为: 38.408
异常值共303条
异常值出现的概率0.0067
3.3 箱型图分析
箱体图Boxplot是一种表示数据分布的方法(wiki:boxplot),一个基本的箱体图从上到下分别表示最大值,上四分位,均值,下四分位,最小值。有的箱体图中还会加入异常值等。
箱体图有以下几个优点:
-
可以直观明了地识别数据中的异常值
-
利用箱体图可以判断数据的偏态和尾重
-
利用箱体图可以比较不同批次的数据形状
箱型图识别异常值标准: 异常值被定义为大于Q1+1.5IQR或小于Q2−1.5IQR的值。Q1是上四分位数,表示全部观察值中有1/4的数据比他大,Q2是下四分位数,表示全部数据中有1/4的数据比他小。IQR是四分位间距,是Q1和Q2的差,其间包含了观察值的一半。用集合表示为:{异常值y| y<Q1-1.5IQL || y>Q2+1.5IQL}
def abrnorVa2(self, col):
colData = self.data[col]
dscr = colData.describe() #利用describle得到75%,25%
#print(colData.describe())
IQR = dscr['75%'] - dscr['25%']
upBoundry = dscr['75%'] + 1.5*IQR #上边界
lowBoundry = dscr['25%'] + 1.5*IQR #下边界
num = (colData < lowBoundry).sum() + (colData > upBoundry).sum() #总数
print(col, "异常值的数目:", num)
print(col, "异常值的数目比:", num/colData.shape[0])
# p = self.data.boxplot(col, return_type='dict') #数量比较大,绘制的箱型图不美观
# x = p['fliers'][0].get_xdata()
# y = p['fliers'][0].get_ydata()
# y.sort()
# for i in range(len(x)):
# if i>0:
# plt.annotate(y[i],xy=(x[i],y[i]) ,xytext=(x[i]+0.05-0.8/(y[i]-y[i-1]),y[i]))
# else:
# plt.annotate(y[i], xy = (x[i],y[i]),xytext = (x[i] +0.08, y[i]))
plt.show()
if __name__ == '__main__':
url = r'movies_metadata.csv'
data = PrePross(url)
data.uniq()
data.abnorVal2('runtime')
输出如下:
runtime 异常值的数目:5900
runtime 异常值的数目比: 0.12976729864074255
对比可以看出,同种数据不同种处理方法,异常值的数目和出现概率也不同。
第四步:数据特征分析
对数据进行质量分析以后,可以通过绘制图表,计算某一些特征值等手段进行数据的特征分析。
4.1 分布分析
分布分析能揭示数据的分布特征和分布类型。想要了解其分布形式是对称的还是非对称的,发现某一些特大或特小值。可通过绘制频率分布表,绘制频率分布直方图,绘制茎叶图进行直观分析。
4.12 定量数据的分布分析
对于定量变量而言,选择“组数”和“组宽”是做频率分布分析时主要的问题。一般步骤为:
- 求极差
- 决定组距与组数
- 决定分点
- 列出频率分布表
- 绘制频率分布直方图
求极差:极差=最大值-最小值
分组: 组数 = 极差/组距
这里我们用vote_average来画一下频率直方图。
def frequDraw(self, col):
colData = self.data[col].describe()
print(colData)
very = colData.max() - colData.min() #极差
print(col,'极差为:%.3f 均值为: %.3f' %(very, colData.mean()))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.hist(self.data[col], bins=50)
plt.xlabel(r'投票数')
plt.ylabel(r'频率')
plt.title(r'频率直方图')
plt.show()
4.13 定性数据的分布分析
对于定性变量,就是非连续变量,可以采用饼图和直方图来描述定性变量的分布。
** 饼图**
饼图的每一个扇形部分代表每一个类型的百分比或频数,每一部分与每一类型的频数成正比,条形图的高度代表每一类型的百分比或频数。
大概最为简单的数据质量分析就在这里了,还有更高级的数据质量分析,推荐大家可以去看《数据挖掘与实战》这一本书。