从大量数据中挖掘出其对决策的潜在关系,并将这些关系运用于决策模型,提供预测性决策支持的方法、工具和过程,这就是数据挖掘。
数据挖掘的基本任务:分类与预测、聚类分析、关联规则、时序模式、偏差检测、智能推荐等。
数据挖掘建模过程
定义挖掘目标
数据取样
数据探索
异常值分析、缺失值分析、相关分析、周期性分析等(详见第3章)
数据预处理
数据筛选、数据变量转换、缺失值处理、坏数据处理、数据标准化、主成分分析、属性选择、数据归约等(详见第3章)
挖掘建模
模型评价
a=[1,2,3]
b=[i+2 for i in a]
#利用map()改写
b=map(lambda x:x+2)
b=list(b)
列表解析的本质是for循环,map()效率更高
s=1
for i in range(1,n+1):
s=s*i
#利用reduce()改写
from functools import reduce
#算出n的阶乘
reduce(lambda x,y:x*y,range(1,n+1))
b=[i for i in range(10) if i>5 and i<8]
#利用filter()改写
b=filter(lambda x:x>5 and x<8,range(10))
b=list(b)
处理方式:
删除存在缺失值的记录、对可能值进行插补、不处理。详见4.1.1节
查看缺失值:
describe()中的count是非空数值,通过与len作差可以得到缺失值数量。
简单统计量分析
3σ原则
数据服从正态分布、在3σ原则下,异常值被定义为一组测定值中与平均值偏差超过三倍标准差的值。
在正态分布的假设下,距离平均值3σ之外的值出现的概率为P(|x-μ|>3σ)≤0.003,属于极小个别的小概率事件。
如果数据不服从正态分布,也可以用远离平均值的多少倍标准差来描述。
箱形图分析
异常值:小于 Q L − 1.5 I Q R Q_L-1.5IQR QL−1.5IQR或大于 Q U + 1.5 I Q R Q_U+1.5IQR QU+1.5IQR的值。
Q L Q_L QL:下四分位数,表示全部观察值中有四分之一的数据取值比它小。
Q U Q_U QU:上四分位数,表示全部观察值中有四分之一的数据取值比它大。
import pandas as pd
catering_sale = './data/catering_sale.xls' # 餐饮数据
data = pd.read_excel(catering_sale, index_col=u'日期') # 读取数据,指定“日期”列为索引列
import matplotlib.pyplot as plt # 导入图像库
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() # 展示箱线图
结合实体业务,确定过滤规则为400以下5000以上为异常数据。
对于定量数据,欲了解其分布形式是对称还是非对称的,发现某些特大或特小的可疑值,可通过绘制频率分布表、频率分布直方图、茎叶图进行直观地分析。
对于定性数据,可用饼图和条形图直观地显示分布情况。
选择“组数”和“组宽”是做频率分析时最主要的问题,一般按以下步骤:
要遵循以下原则:
import pandas as pd
dish_profit = './data/catering_dish_profit.xls' #餐饮菜品盈利数据
data = pd.read_excel(dish_profit, index_col = u'菜品名')
data = data[u'盈利'].copy()
data.sort_index(ascending = False)
sizes=[i/data.sum() for i in data]
colors=['red','green']
plt.pie(sizes,labels=data.index,colors=colors,autopct='%1.1f%%',shadow=True,startangle=90)
plt.axis('equal')
用电量时序图
又称帕累托分析,原理是帕累托法则,又称20/80定律。
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=0.02"))
#添加注释,即85%处的标记。这里包括了指定箭头样式。
plt.ylabel(u'盈利(比例)')
plt.show()
计算相关系数
Pearson相关系数
Spearman秩相关系数
判定系数
相关系数的平方,用来衡量回归方程对y的解释程度。
判 定 系 数 取 值 范 围 : 0 ≤ r 2 ≤ 1 , 越 接 近 1 相 关 性 越 强 。 判定系数取值范围:0≤r^2≤1,越接近1相关性越强。 判定系数取值范围:0≤r2≤1,越接近1相关性越强。
分析菜品销售量之间的相关性,得到不同菜品之间的关系。
菜品相关系数矩阵:
data.corr()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rwCR2avc-1630063913270)(C:\Users\86139\AppData\Roaming\Typora\typora-user-images\image-20210825152043826.png)]
功能:绘制线性二维图、折线图
使用格式:
功能:绘制饼型图
使用格式:plt.pie(size)#size:各个扇形比例
labels='A','B','C','D'
sizes=[15,30,45,10]
colors=['yellow','gold','blue','green']
explode=(0,0.1,0,0)#突出显示,这里突出第二块
plt.pie(sizes,explode=explode,labels=labels,colors=colors,autopct='%1.1f%%',shadow=True,startangle=90)
plt.axis('equal')
tips:0-20等分成100份:x=np.linspace(0,20,100)
功能:绘制二维条形直方图,可显示数据的分布情况
使用格式:plt.hist(x,y)
x是待绘制直方图的一维数组,y可以是整数,表示均分为y组,也可以是列表,列表各个数字为分组的边界点。
功能:绘制样本数据的箱形图
使用格式:D.boxplot()/D.plot(kind=‘box’)
功能:绘制x或y轴的对数图形。
使用格式:D.plot(logx=True)
功能:绘制误差条形图
使用格式:D.plot(yerr=error)
如果设置参数xerr=error,则在x轴方向画出误差棒图。
删除原始数据集中的无关数据、重复数据,平滑噪声数据,筛选掉与挖掘主题无关数据,处理缺失值、异常值等。
插值法处理:拉格朗日插值法(Scipy支持)、牛顿插值法
# 自定义列向量插值函数
# s为列向量,n为被插值的位置,k为取前后的数据个数,默认为5
def ployinterp_column(s, n, k=5):
y = s[list(range(n - k, n)) + list(range(n + 1, n + 1 + k))] # 取数
y = y[y.notnull()] # 剔除空值
return lagrange(y.index, list(y))(n) # 插值并返回插值结果
# 逐个元素判断是否需要插值
for i in data.columns:
for j in range(len(data)):
if (data[i].isnull())[j]: # 如果为空即插值。
data.loc[[j], [i]] = ployinterp_column(data[i], j)
不同评价指标往往具有不同量纲,不进行处理会影响数据分析结果。
最小-最大规范化
零-均值规范化
小数定标规范化
有些数据挖掘算法,特别是某些分类算法(如ID3算法、Apripri算法等),要求数据是分类属性形式,会用到将连续属性变换成分类属性的方法,即连续属性离散化。
# 等宽离散化,各个类比依次命名为0,1,2,3
d1 = pd.cut(data, k, labels=range(k))
# 等频率离散化
w = [1.0 * i / k for i in range(k + 1)]
w = data.describe(percentiles=w)[4:4 + k + 1]
w[0] = w[0] * (1 - 1e-10)
d2 = pd.cut(data, w, labels=range(k))
# KMeans
from sklearn.cluster import KMeans
kmodel = KMeans(n_clusters=k, n_jobs=4)
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()] # 把首末边界点加上
d3 = pd.cut(data, w, labels=range(k))
def cluster_plot(d, k): # 自定义作图函数来显示聚类结果
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 3))
for j in range(0, k):
plt.plot(data[d == j], [j for i in d[d == j]], 'o')
plt.ylim(-0.5, k - 0.5)
return plt
cluster_plot(d1, k).show()
cluster_plot(d2, k).show()
cluster_plot(d3, k).show()
数据规约产生更小但保持原数据完整性的新数据集。
import pandas as pd
inputfile = './data/principal_component.xls'
data = pd.read_excel(inputfile, header=None)
from sklearn.decomposition import PCA
pca = PCA()
pca.fit(data)
pca.components_ # 返回模型的各个特征向量
pca.explained_variance_ratio_ # 返回各个成分各自的方差百分比
建模步骤:
特征筛选:方法主要包含在Scikit_Learn的feature_selection库中
对银行降低贷款拖欠率的数据进行逻辑回归建模:
import pandas as pd
filename="./data/bankloan.xls"
data=pd.read_excel(filename)
x=data.iloc[:,:8]
y=data.iloc[:,8]
from sklearn.linear_model import LogisticRegression as LR
from sklearn.linear_model import RandomizedLogisticRegression as RLR
rlr=RLR()#随机逻辑回归模型,筛选变量
rlr.fit(x,y)
rlr.get_support()#获取特征筛选结果
#也可以通过.scores_方法获取各个特征的分数
rlr.scores_
print(u'有效特征为:%s' % ','.join(data.columns[rlr.get_support(indices=True)]))
#Indices是False,就返回一个类型是boolean的数组,如果indices是True,就返回一个整型数组
x=data.loc[:,data.columns[rlr.get_support(indices=True)]]
lr=LR()
lr.fit(x,y)
print("模型平均正确率:%s" % lr.score(x,y))
import pandas as pd
filename='./data/sales_data.xls'
data=pd.read_excel(filename,index_col=u'序号')
#类别标签转换
data[data==u"好"]=1
data[data==u"是"]=1
data[data==u"高"]=1
data[data!=1]=-1
x=data.iloc[:,:3].astype(int)
y=data.iloc[:,3].astype(int)
from sklearn.tree import DecisionTreeClassifier as DTC
dtc=DTC(criterion='entropy')#基于信息熵
dtc.fit(x,y)
#导入相关函数,可视化决策树
# 导出的结果是dot文件,需安装Graphviz才能转换为pdf或png格式
from sklearn.tree import export_graphviz # 导入可视化决策树
with open('tree.dot', 'w') as f:
f = export_graphviz(dtc, feature_names=x.columns, out_file=f)
import pandas as pd
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation # 导入全连接层,激活层
from sklearn.metrics import confusion_matrix # 导入混淆矩阵
import matplotlib.pyplot as plt
model=Sequential()
model.add(Dense(input_dim=3, units=10))
model.add(Activation('relu'))
model.add(Dense(input_dim=10, units=1))
model.add(Activation('sigmoid'))#0-1输出,用sigmoid做激活函数
model.compile(loss = 'binary_crossentropy', optimizer = 'adam')
#编译模型。二元分类,指定损失函数为binary_crossentropy,模式为binary
#另外常见的损失函数还有mean_squared_error、categorical_crossentropy等
#求解方法我们指定用adam,还有sgd、rmsprop等
model.fit(x, y, nb_epoch = 100, batch_size = 10) #训练模型,学习一千次
yp = model.predict_classes(x).reshape(len(y)) #分类预测
# 使用K-Means算法聚类消费行为特征数据
import pandas as pd
inputfile = './data/consumption_data.xls' # 销量及其他属性数据
# outputfile = './tmp/data_type.xls' # 保存结果的文件名
k = 3 # 聚类的类别
iteration = 500 # 聚类最大循环次数
data = pd.read_excel(inputfile, index_col='Id') # 读取数据
data_zs = 1.0 * (data - data.mean()) / data.std() # 数据标准化
from sklearn.cluster import KMeans
model = KMeans(n_clusters=k, n_jobs=4, max_iter=iteration) # 分为k类,并发数4
model.fit(data_zs) # 开始聚类
# 简单打印结果
r1 = pd.Series(model.labels_).value_counts() # 统计各个类别的数目
r2 = pd.DataFrame(model.cluster_centers_) # 找出聚类中心
r = pd.concat([r2, r1], axis=1) # 横向连接(0是纵向),得到聚类中心对应的类别下的数目
r.columns = list(data.columns) + [u'类别数目'] # 重命名表头
print(r)
# 详细输出原始数据及其类别
r = pd.concat([data, pd.Series(model.labels_, index=data.index)], axis=1) # 详细输出每个样本对应的类别
r.columns = list(data.columns) + [u'聚类类别'] # 重命名表头
# r.to_excel(outputfile) # 保存结果
r
TSNE提供有效数据降维方式,能在2维或3维空间中展示聚类结果。
from sklearn.manifold import TSNE
tsne = TSNE(random_state=0)
tsne.fit_transform(data_zs) # 进行数据降维
tsne = pd.DataFrame(tsne.embedding_, index=data_zs.index)
plt.figure()
d = tsne[r[u'聚类类别'] == 0]
plt.plot(d[0], d[1], 'r.')
d = tsne[r[u'聚类类别'] == 1]
plt.plot(d[0], d[1], 'go')
d = tsne[r[u'聚类类别'] == 2]
plt.plot(d[0], d[1], 'b*')
# plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v9C7ue8m-1630063913274)(C:\Users\86139\AppData\Roaming\Typora\typora-user-images\image-20210827111149254.png)]
from __future__ import print_function
import pandas as pd
# from apriori import * # 导入自行编写的apriori函数
inputfile = r'.\data\menu_orders.xls'
outputfile = r'.\data\apriori_rules.xls'
data = pd.read_excel(inputfile, header=None) # 读取数据
print(data)
print(u'\n转换原始数据至0-1矩阵...')
ct = lambda x: pd.Series(1, index=x[pd.notnull(x)]) # 转换0-1矩阵的过滤函数
b = list(map(ct, data.values)) # 用map方式执行
data = pd.DataFrame(b).fillna(0) # 实现矩阵转换,空值用0填充
print(u'\n转换完毕.')
print(data)
print(data.sum(),len(data))
del b # 删除中间变量b节省内存
support = 0.2 # 最小支持度
confidence = 0.5 # 最小执行度
ms = '---' # 连接符,默认’--‘ ,用来区分不同元素,如A--B.需要爆照原始表格中不含有该字符
find_rule(data,support,confidence,ms).to_excel(outputfile) # 保存结果
拿到一个观察值序列,首先进行纯随机性和平稳性检验,将序列分为不同类型后采用不同的分析方法:
差分法:时间序列在t与t-1时刻的差值。
平稳性检验:
模型 | ACF | PACF |
---|---|---|
AR§ | 衰减趋于零(几何型或振荡型) | p阶后截尾 |
MA(q) | q阶后截尾 | 衰减趋于零(几何型或振荡型) |
ARMA(p,q) | q阶后衰减趋于零(几何型或振荡型) | p阶衰减趋于零(几何型或振荡型) |
截尾:落在置信区间内(95%的点都符合规则)
ARIMA建模流程:
# arima时序模型
import pandas as pd
discfile = './data/arima_data.xls'
forecastnum = 5
data = pd.read_excel(discfile, index_col=u'日期')
data.head(3)
# 时序图
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
data.plot()
plt.show()
# 差分后的结果
D_data = data.diff().dropna()#diff默认值是1,默认一阶差分
D_data.columns = [u'销量差分']
D_data.plot() # 时序图
plot_acf(D_data) # 自相关图
from statsmodels.graphics.tsaplots import plot_pacf
plot_pacf(D_data,lags=12) # 偏自相关图,显示前20个
plot_pacf(D_data) # 偏自相关图,显示所有元素
print(u'差分序列的ADF检验结果为:',ADF(D_data[u'销量差分'])) # 平稳性检测
#pvalue单位根选取标准为0.05,小于0.05则认为平稳
#只用了一阶差分,所以d=1
# 白噪声检验
from statsmodels.stats.diagnostic import acorr_ljungbox
print(u'差分序列的白噪声检验结果为:', acorr_ljungbox(D_data, lags=1)) # 返回统计量和p值
#p值小于0.05,认为不是白噪声序列
from statsmodels.tsa.arima_model import ARIMA
#定阶
pmax = int(len(data)/10) #一般阶数不超过length/10
qmax = int(len(data)/10) #一般阶数不超过length/10
bic_matrix = [] #bic矩阵
for p in range(pmax+1):
tmp = []
for q in range(qmax+1):
try: #存在部分报错,所以用try来跳过报错。
tmp.append(ARIMA(data, (p,1,q)).fit().bic)
except:
tmp.append(None)
bic_matrix.append(tmp)
print(bic_matrix)
from statsmodels.tsa.arima_model import ARIMA
# 定阶,自相关系数和偏自相关系数究竟是截尾还是拖尾
data['销量'] = data['销量'].astype(float)
pmax = int(len(D_data) / 10) # 一般阶数不超过length/10
qmax = int(len(D_data) / 10) # 一般阶数不超过length/10
bic_matrix = [] # bic矩阵
for p in range(pmax + 1):
tmp = []
for q in range(qmax + 1):
try: # 存在部分报错,所以用try来跳过报错。
tmp.append(ARIMA(data, (p, 1, q)).fit().bic)
except:
tmp.append(None)
bic_matrix.append(tmp)
bic_matrix = pd.DataFrame(bic_matrix) # 从中可以找出最小值
p, q = bic_matrix.stack().idxmin() # 先用stack展平,然后用idxmin找出最小值位置。
print(u'BIC最小的p值和q值为:%s、%s' % (p, q))#得到p、q;p自相关系数,q偏自相关系数
model = ARIMA(data, (p, 1, q)).fit() # 建立ARIMA(0, 1, 1)模型
model.summary2() # 给出一份模型报告
model.forecast(5) # 作为期5天的预测,返回预测结果、标准误差、置信区间。
预测结果4873.9665477在置信区间[4730.72112437, 5017.21197102]内,预测结果是较为准确的。
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt # 带入图像库
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文指标
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
inputfile = r'.\data\consumption_data.xls'
k = 3 #聚类的类别
threshold = 2 # 离群点阈值
iteration = 500 # 聚类最大循环次数
readExcel = pd.ExcelFile(inputfile)
data = pd.read_excel(readExcel,index_col='Id')#读取数据
data_zs = 1.0*(data-data.mean(axis=0))/data.std(axis=0) # 标准差标准化
model = KMeans(n_clusters=k,n_jobs=4,max_iter=iteration)
model.fit(data_zs)
r = pd.concat([data_zs,pd.Series(model.labels_,index=data.index)],axis = 1)
r.columns = list(data.columns) + [u'聚类类别']
norm =[]
for i in range(k):
norm_tmp = r[['R','F','M']][r[u'聚类类别'] == i]-model.cluster_centers_[i]
norm_tmp = norm_tmp.apply(np.linalg.norm,axis=1)
norm.append(norm_tmp/norm_tmp.median())#求相对距离并添加
norm = pd.concat(norm) # 合并
norm[norm <= threshold].plot(style = 'go' ) #正常点
discrete_points = norm[norm>threshold]
discrete_points.plot(style='ro')#离群点
for i in range(len(discrete_points)):
id = discrete_points.index[i]
n = discrete_points.iloc[i]
plt.annotate('(%s , %0.2f)'%(id,n),xy = (id,n),xytext = (id,n))
plt.xlabel(u'编号')
plt.ylabel(u'相对距离')
plt.show()