内容分为两个部分:
第一部分:《Python数据分析与挖掘实战》第三章 的内容;
第二部分:自己编码过程中这部分的学习总结。
课件 PDF 和 源码 移步到Github : https://github.com/Stormzudi/Python-Data-Mining
邮箱:[email protected]
缺失值分析,在下面的第二部分。
异常值是指样本中的个别值,其数值明显偏离其余的观测值。异常值也称为离群点,异常值的分析也称为离群点分析。通常有以下几种方法:
(1)简单的统计量分析
(2)3 σ \sigma σ 原则
(3)箱型图分析
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-1_abnormal_check.py
# @Author: Stormzudi
# @Date : 2020/7/19 19:08
import pandas as pd
import matplotlib.pyplot as plt # 导入图像库
# 使用describe()函数就可以查看数据的基本情况
catering_sale = '../data/catering_sale.xls' # 餐饮数据
data = pd.read_excel(catering_sale, index_col = u'日期') # 读取数据,指定“日期”列为索引列
print(data.describe())
# 餐饮销额数据异常值检测代码
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.figure() # 建立图像
p = data.boxplot(return_type='dict') # 画箱线图,直接使用DataFrame的方法
x = p['fliers'][0].get_xdata() # 'flies'即为异常值的标签
y = p['fliers'][0].get_ydata()
y.sort() # 从小到大排序,该方法直接改变原对象
# 用annotate添加注释
# 其中有些相近的点,注解会出现重叠,难以看清,需要一些技巧来控制。
# 以下参数都是经过调试的,需要具体问题具体调试。
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() # 展示箱线图
一致性分析的任务是比较数据是否矛盾,和不相容性。要保证同一份数据在不同的分析师手里是一样的。
分布分析: 揭示数据的分布特征和分布类型。
(1) 对于定量数据,欲了解其分布形式是对称的还是非对称的,发现某些特大或特小的可疑值,可通过绘制频率分布表
、绘制频率分布直方图
、绘制茎叶图
进行直观地分析;
(2) 对于定性分类数据,可用饼图
和条形图
直观地显示分布情况。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-2-1_statistics_analyze.py
# @Author: Stormzudi
# @Date : 2020/7/19 21:21
"""
表3-2是描述菜品“捞起生鱼片”在2014年第二个季度的销售数据,
通过表中数据绘制销售量的频率分布表、频率分布图,对该定量数据做出相应的分析。
"""
import pandas as pd
import matplotlib.pyplot as plt
catering_sale = '../data/catering_sale.xls' # 餐饮数据
data = pd.read_excel(catering_sale, usecols=[1])
data = data.fillna(0).values # 将缺失值替换为那个常数值0
number = len(data) # 统计出分组
# 设置长度为 8 的分组
num0 = []; num1 = []; num2 = []
num3 = []; num4 = []; num5 = []
num6 = []; num7 = []
for i in range(number):
if data[i,0]<500:
num0.append(data[i,0])
elif data[i,0]<1000:
num1.append(data[i,0])
elif data[i,0]<1500:
num2.append(data[i,0])
elif data[i,0]<2000:
num3.append(data[i,0])
elif data[i,0]<2500:
num4.append(data[i,0])
elif data[i,0]<3000:
num5.append(data[i,0])
elif data[i,0]<3500:
num6.append(data[i,0])
elif data[i,0]<4000:
num7.append(data[i,0])
# 统计频数
num = [len(num0), len(num1), len(num2), len(num3), len(num4), len(num5), len(num6), len(num7)]
print(num)
# 绘制直方图
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.bar(['0~500','500~1000','1000~1500','1500~2000','2000~2500','2500~3000','3000~3500','>3500'] ,
num, label='季度销售额频率分布直方图')
plt.legend()
plt.xlabel('日销售额/元')
plt.ylabel('频数')
plt.title('销售额的频率分布直方图')
plt.show()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-2-2_statistics_analyze.py
# @Author: Stormzudi
# @Date : 2020/7/19 22:06
"""
绘制菜品A. B、C在某段时间的销售量的分布图
"""
import matplotlib.pyplot as plt
import seaborn as sns # seaborn画出的图更好看,且代码更简单,缺点是可塑性差
sns.set(color_codes=True) # seaborn设置背景
# 菜品A、B、C的数量为
num = [330, 110, 560]
# 绘制饼图
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
labels = ['菜品A','菜品B','菜品C']
plt.pie(num, labels=labels, autopct='%1.1f%%', shadow=False, startangle=150)
plt.title("菜品销售量分布(饼图)")
plt.axis('equal') # 该行代码使饼图长宽相等
# 绘制直方图
fig, ax = plt.subplots()
ax.bar(labels,num, color='SkyBlue', label='Men')
ax.set_title('菜品的销售量分布(条形图)')
plt.show()
对比分析主要有以下两种形式。
(1) 绝对数比较
绝对数比较是利用绝对数进行对比,从而寻找差异的一种方法。
(2) 相对数比较
相对数比较是由两个有联系的指标对比计算的,用以反映客观现象之间数量联系程度的综合指标,其数值表现为相对数。例如:表格、条形图、折线图。
这部分数据没有,就没画图,可以移步到:,学习折线图如何绘制。
统计量分析主要分成两个部分:
(1)集中趋势度量:中位数、均值、众数
(2)离中趋势度量:极差、标准差、变异系数、四分位数间距
注意:以下代码只是针对于dataframe结构的数据。如果是列表、ndarray数据结构,需要一个个去参考对应的统计量分析方法。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-2_statistics_analyze.py
# @Author: Stormzudi
# @Date : 2020/7/19 19:30
# 餐饮销量数据统计量分析
from __future__ import print_function
import pandas as pd
catering_sale = '../data/catering_sale.xls' #餐饮数据
data = pd.read_excel(catering_sale, index_col = u'日期') #读取数据,指定“日期”列为索引列
data = data[(data[u'销量'] > 400)&(data[u'销量'] < 5000)] #过滤异常数据
statistics = data.describe() #保存基本统计量
statistics.loc['range'] = statistics.loc['max']-statistics.loc['min'] #极差
statistics.loc['var'] = statistics.loc['std']/statistics.loc['mean'] #变异系数
statistics.loc['dis'] = statistics.loc['75%']-statistics.loc['25%'] #四分位数间距
print(statistics)
结果:
销量
count 195.000000
mean 2744.595385
std 424.739407
min 865.000000
25% 2460.600000
50% 2655.900000
75% 3023.200000
max 4065.200000
range 3200.200000
var 0.154755
dis 562.600000
周期性分析是探索某个变量是否随着时间变化而呈现出某种周期变化趋势。
分析数据集catering_fish_congee.xls是否具有某种周期变化趋势。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-2-4_statistics_analyze.py
# @Author: Stormzudi
# @Date : 2020/7/20 15:19
"""
功能:周期性分析
"""
import pandas as pd
import matplotlib.pyplot as plt
catering_sale = '../data/catering_fish_congee.xls' # 餐饮数据
data = pd.read_excel(catering_sale, usecols=[1])
data = data.fillna(0).values # 将缺失值替换为那个常数值0
# 绘制折线图
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.plot(data, 'ko--')
plt.ylabel('日销售量')
plt.title('销售额的折线图')
plt.show()
贡献度分析又叫二八分析,就是80%的利润是来自于20%的最畅销的产品。通过贡献度分析可以指定投资策略。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-3_dish_pareto.py
# @Author: Stormzudi
# @Date : 2020/7/20 15:19
# 菜品盈利数据 帕累托图
from __future__ import print_function
import pandas as pd
import matplotlib.pyplot as plt #导入图像库
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
# 初始化参数
dish_profit = '../data/catering_dish_profit.xls' #餐饮菜品盈利数据
data = pd.read_excel(dish_profit, index_col = u'菜品名')
data = data[u'盈利'].copy()
# data.sort(ascending = False)
plt.figure()
data.plot(kind='bar')
plt.ylabel(u'盈利(元)')
p = 1.0*data.cumsum()/data.sum()
p.plot(color = 'r', secondary_y = True, style = '-o',linewidth = 2)
plt.annotate(format(p[6], '.4%'), xy = (6, p[6]), xytext=(6*0.9, p[6]*0.9), arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2")) #添加注释,即85%处的标记。这里包括了指定箭头样式。
plt.ylabel(u'盈利(比例)')
plt.show()
相关性分析: 分析连续变量之间线性相关程度的强弱,并用适当的统计指标表示出来的过程称为相关分析。
PS: 相关性分析可以使用专门的统计学软件:SPSS、R语言进行分析。
# statsmodels macro data的散布图矩阵
sns.pairplot(trans_data, diag_kind='kde', plot_kws={
'alpha': 0.2})
plt.show()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-4_correlation_analysis.py
# @Author: Stormzudi
# @Date : 2020/7/20 15:19
# 餐饮销量数据相关性分析
from __future__ import print_function
import pandas as pd
catering_sale = '../data/catering_sale_all.xls' # 餐饮数据,含有其他属性
data = pd.read_excel(catering_sale, index_col = u'日期') # 读取数据,指定“日期”列为索引列
data.corr() # 相关系数矩阵,即给出了任意两款菜式之间的相关系数
print(data.corr())
统计特征函数用于计算数据的均值、方差、标准差、分位数、相关系数和协方差等。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-3-1_Pandas_statistic_analyze.py
# @Author: Stormzudi
# @Date : 2020/7/20 16:49
"""
3.3.1基本统计特征函数
"""
import pandas as pd
import numpy as np
# 运用字典生成DataFrame数据集
data = {
'state': ['Ohio','Ohio','Ohio','Nevada','Nevada'],
'year': [2015,2016,2017,2001,2002],
'pop': [1.5,1.7,3.6,2.4,2.9]
}
frame2 = pd.DataFrame(data, index=['one','two','three','four','five'],columns=['year','state','pop'])
# 对数据样本的指标"pop"进行基本统计特征分析
print(frame2['pop'].sum()) # 计算数据样本的总和(按列计算)。
print(frame2['pop'].mean()) # 计算数据样本的算术平均数。
print(frame2['pop'].var()) # 计算数据样本的方差。
print(frame2['pop'].std()) # 计算数据样本的标准差。
# 计算数据样本的Spearman(Pearson)相关系数矩阵
D = pd.DataFrame([range(1, 8), range(2, 9)]) # 生成样本D,一行为1~7,一行为2~8
D.corr(method='pearson') # 计算相关系 数矩阵
S1 = D.loc[0] # 提取第一行
S2 = D.loc[1] # 提取第二行
var = S1.corr(S2, method='pearson') # 计算S1. s2的相关系数
print(var)
# 计算数据样本的协方差矩阵
D = pd.DataFrame(np.random.randn(6, 5)) # 产生6*5随机矩阵
D.cov() # 计算协方差矩阵
print(D.cov())
# 计算数据样本的偏度(三阶矩) /峰度(四阶矩)。
D = pd.DataFrame(np.random.randn(6,5)) #产生6X5随机矩阵
D.skew()
D.kurt()
# 直接给出样本数据的描述
D = pd.DataFrame(np.random.randn(6, 5))
D.describe()
除了上面的基础函数外,还有累积计算(cum)和滚动计算(pd.rolling_)。
Python的主要作图库是Matplotlib,同时,作图也可以是Matplotlib和Pandas相互结合着使用。
在作图之前,通常要加载以下代码。
import matplotlib.pyplot as plt # 导入作图库
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.figure(figsize = (7, 5)) # 创建图像区域, 指定比例
作图完成后,一般通过plt.show()来显示作图结果。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 3-4-1_plot.py
# @Author: Stormzudi
# @Date : 2020/7/20 17:16
"""
3.3.3 统计作图函数
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt # 导入作图库
plt.rcParams ['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] =False # 用来正常显示负号
plt.figure(figsize = (7, 5)) # 创建图像区域,指定比例
# (1) plot
x = np.linspace(0,2*np.pi,50) #x坐标输入
y = np.sin(x) #计算对应x的正弦值
plt.plot(x, y, 'bp--') #控制图形格式为蓝色带星虚线, 显示正弦曲线
plt.show()
# (2) pie
# The slices will be ordered and plotted counter-clockwise.
labels = ['Frogs', 'Hogs', 'Dogs','Logs'] #定义标签
sizes = [15, 30, 45, 10] # 每一块的比例
colors = ['yellowgreen', 'gold', 'lightskyblue','lightcoral'] # 每一块的颜色
explode = (0, 0.1, 0, 0) #突出显示,这里仅仅突出显示第二块(即'Hogs' )
plt.pie(sizes, explode=explode, labels=labels, colors=colors, autopct='81.1f88', shadow=True, startangle=90)
plt.axis('equal') #显示为圆(避免比例压缩为椭圆)
plt.show()
# (3) hist
x = np.random. randn(1000) # 1000个服从正态分布的随机数
plt.hist(x, 10) # 分成10组进行绘制直方图
plt. show()
# (4) boxplot
x = np.random.randn(1000) #1000个服从正态分布的随机数
D = pd.DataFrame([x, x+1]).T #构造两列的DataFrame
D.plot(kind = 'box') #调用Series内置的作 图方法画图,用kind参数指定箱形图box
plt.show()
# (5) plot(logx = True)/plot(logy = True)
x = pd.Series(np.exp(np.arange(20))) # 原始数据
x.plot(label = u'原始数据图', legend = True)
plt.show()
x.plot(logy = True, label = u'对数数据图', legend = True)
plt.show()
# (6) plot(yerr = error)
error = np.random.randn(10) # 定义误差列
y = pd.Series(np.sin(np.arange(10))) # 均值数据列
y.plot(yerr = error) # 绘制误差图
plt.show()
要特别说明的是,在数据可视化中,由于主要使用Pandas作为数据探索和分析的工具,因此我们介绍的作图工具都是Matplotib和Pandas结合使用。一方面,Matplotib 是作图工具的基础,Pandas 作图依赖于它;另-方面,Pandas 作图有着简单直接的优势,因此,两者相互结合,往往能够以最高的效率作出符合我们需要的图。
第二部分:主要内容是运用在机器学习中,对数据进行预处理部分。
包括:特征工程
、文本特征提取
、预处理
、数据降维
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 01feature_extraction.py
# @Author: ZhuNian
# @Date : 2020/6/20 17:18
"""
位置:思维导图“机器学习”
章节:01-2 # 获取特征并且数值化
章节:01-3 # 字典数据抽取
章节:01-4 # 中文 特征化
章节:01-5 # tf_df分析问题
"""
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction import DictVectorizer
import jieba # 用于分段
from sklearn.feature_extraction.text import TfidfVectorizer
def CountVec():
# 实例化类CountVectorizer
vector = CountVectorizer()
# 调用fit_transform输出并转换
res = vector.fit_transform(["life is short,i like python", "life is too long, i don't like python",
"life is too long, i like matlab"])
# 打印结果
print(vector.get_feature_names()) # 获取输入字段中,所有的特征
print(res.toarray()) # 输出具有或者不具有【0,1】此字段
def dictver():
"""
字典数据抽取
return: None
"""
simple = [{
'city': '北京', 'temperature': 100},
{
'city': '上海', 'temperature': 200},
{
'city': '广州', 'temperature': 300}]
# 实例化一个对象
dict = DictVectorizer()
dict1 = DictVectorizer(sparse = False)
# 调用fit_transfrom()
data = dict.fit_transform(simple) # 返回的时一个sparse矩阵(三元表)
data1 = dict1.fit_transform(simple) # 返回的是一个ndaary矩阵
# 看出返回特征值的实例
print(dict.get_feature_names())
print(data)
print(data1)
def funcname():
# 文本
data = ["今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
"我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
"如果只用- -种方式了解某样事物,你就不会真正了解它。解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"
]
con = [list(jieba.cut(i)) for i in data] # 分割一整段,转化成字符串
c = [' '.join(i) for i in con] # 列表中的字符串,转化成”有空格的“列表:['今天 很 残酷 , 明天 更 残酷']...
print(c)
return c
def hanzivec():
"""
中文 特征化
return: None
"""
input = funcname()
cv = CountVectorizer()
data = cv.fit_transform(input)
print(cv.get_feature_names())
print(data.toarray())
def tfdf():
"""
tf_df分析问题
return: None
"""
input = funcname()
tfidf = TfidfVectorizer()
data = tfidf.fit_transform(input)
print(tfidf.get_feature_names())
print(data.toarray())
if __name__ == '__main__':
# CountVec()
# dictver()
# funcname()
hanzivec()
# tfdf()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 02Feature_pretreatment.py
# @Author: ZhuNian
# @Date : 2020/6/21 16:42
"""
1.特征预处理-归一化
2.特征预处理-标准化
"""
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler
def Normalization():
"""
归一化处理
不调用库函数
"""
data = np.array([[90, 2, 10, 40],[60, 4, 15, 45],[75, 3, 13, 46]])
row = np.shape(data)[0]
col = np.shape(data)[1]
D = np.ones((row, col))
"""
运用函数式编程:
input:data,D
output: NL_data
"""
f = lambda x, max_data, min_data: (x - min_data) / (max_data - min_data) # 定义函数f
for i in range(col):
D[:, i] = f(data[:, i], max(data[:, i]), min(data[:, i]))
# 可以指定区间[mx, mi], 不再是区间[0, 1]
# mx = 2; mi = 1
# D[:, i] = D[:, i]*(mx - mi) + mi
print(D)
def mm():
"""
归一化处理
运用sklearn库的MinMaxScaler()
"""
mm = MinMaxScaler()
data = mm.fit_transform([[90, 2, 10, 40],[60, 4, 15, 45],[75, 3, 13, 46]])
print(data)
def Standardized():
"""
标准化处理
不调用库函数
"""
data = np.array([[90, 2, 10, 40],[60, 4, 15, 45],[75, 3, 13, 46]])
row = np.shape(data)[0]
col = np.shape(data)[1]
mean = np.mean(data, axis=0) # 获取每个指标的平均值
arr_std = np.std(data, axis=0, ddof=1) # 获取每个指标的标准差
data_st = np.zeros((row, col)) # 标准化后的数据
for i in range(col):
st = (data[:, i] - mean[i])/arr_std[i]
data_st[:, i] = st
print(data_st)
def standardized():
"""
标准化处理
调用库函数
"""
sd = StandardScaler()
data = np.array([[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]])
data = sd.fit_transform(data)
print(data)
if __name__ == '__main__':
Normalization()
mm()
Standardized()
standardized()
# -*- coding: utf-8 -*-
# @Time : 2020/6/3 17:42
# @Author : Zudy
# @FileName: c7.py
'''
1.异常值剔除: 拉以达法则(3σ 法则)
2.缺失值处理: SimpleImputer()
3.缺失值处理:Pandas
'''
import pandas as pd
import numpy as np
from numpy import NaN as NA
from sklearn.impute import SimpleImputer
def yuchang():
"""
异常值处理
拉以达法则(3σ 法则)
"""
inputfile = 'F:/Python/Python_learning/HBUT/预处理/test1_four.xlsx'
data = pd.read_excel(inputfile, sheet_name='Sheet2', index_col='日期')
data1 = data['SS81516']
# 设定法则的左右边界
left = data1.mean() - 3 * data1.std()
right = data1.mean() + 3 * data1.std()
# 获取在范围内的数据
new_num = data1[(left < data1) & (data1 < right)]
t_f = (left < data1) & (data1 < right)
print(t_f)
def queshi():
"""
缺失值填补
调用库函数 SimpleImputer()
"""
data = np.array([[1, 2, 3], [2, NA, 4], [5, 6, 9]])
imputer = SimpleImputer(missing_values=NA, strategy = "mean") # 默认的是每列指标
r = imputer.fit_transform(data)
print(r)
def Queshi():
"""
缺失值填补
运用 DataFrame()
"""
data = np.array([[1, 2, 3], [2, NA, 4], [5, 6, 9]])
data = pd.DataFrame(data)
data_new = data.fillna(data.mean()) # 默认了运用每列的均值进行填补
print(data_new)
def replace():
"""
批量替换
运用 Pandas中的replace()
"""
data_ = [[1, 2, 3], [2, '?', 4], [5, 6, 9]]
df = pd.DataFrame(data_)
data_new = df.replace('?', NA)
print(data_new)
if __name__ == '__main__':
yuchang()
queshi()
Queshi()
replace()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : pre-dimension-reduction.py
# @Author: ZhuNian
# @Date : 2020/6/25 22:46
"""
1 多个文件进行特征值匹配,(按照文件中的共同特征值进行合并)
2 将数据进行降维处理
"""
import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
# 读取四张表的数据
prior = pd.read_csv("./instacart-market-basket-analysis/instacart/order_products__prior.csv")
products = pd.read_csv("./instacart-market-basket-analysis/instacart/products.csv")
orders = pd.read_csv("./instacart-market-basket-analysis/instacart/orders.csv")
aisles = pd.read_csv("./instacart-market-basket-analysis/instacart/aisles.csv")
# 合并到一张表中
_mg = pd.merge(prior, products, on=['product_id', 'product_id'])
_mg = pd.merge(_mg, orders, on=['order_id', 'order_id'])
_mg = pd.merge(_mg, aisles, on=['aisle_id', 'aisle_id'])
# print(_mg.head())
# print(_mg.columns)
# 实现交叉表
cross = pd.crosstab(_mg['user_id'], _mg['aisle'])
print(cross.head())
# 主成分分析PCA
pca = PCA(n_components=0.9) # 保留90%的信息量
data = pca.fit_transform(cross)
print(np.shape(data))