前言:对于一个转行做数据分析的我来说,最让自己头疼的是搞不清数据分析的流程、方式,不知道该怎么开始一个练手项目。逛知乎、找度娘、看数据分析书籍,写这篇文章目的是想巩固知识,让自己不断复习!
数据分析流程
需求层:目标确定
数据层
分析层
输出层
1. 需求层:目标确定,通常是你的同事或上级提出分析需求
注:如果是自己提出的需求,需要注意以下三点a.选择感兴趣的行业b.保证有准确数据供应c.选择细分切入
2. 数据层:数据获取-数据清洗整理,会占据数据分析的50%+时间
a.数据获取:公开网站(国家统计局、各行业网站等),专门做数据整理的网站(淘宝),自行搜索收集(调查问卷、复制粘贴)
b.数据清洗整理:数据异常值、缺失值、重复记录、非数值型数据转标签数据等;
(1)缺失值处理:判断缺失值isnull/notnull,删除.dropna(),众数/中位数填充缺失值.fillna()/.replace(),拉格朗日插值法
s.dropna(inplace=True)
s.fillna(0,inplace=True,method = 'pad'/'bfill')
s.replace(旧,新,inplace=True)
#拉格朗日插值法
from scipy.interpolate import lagrange
def na_c(s,n,k=5):
y = s[list(range(n-k,n+1+k))] # 取数
y = y[y.notnull()] # 剔除空值
return(lagrange(y.index,list(y))(n))
# 创建函数,做插值,由于数据量原因,以空值前后5个数据(共10个数据)为例做插值
na_re = []
for i in range(len(data)):
if data.isnull()[i]:
data[i] = na_c(data,i)
print(na_c(data,i))
na_re.append(data[i])
(2)异常值处理:
3西格玛原则:如果数据服从正态分布,异常值被定义为一组测定值中与平均值的偏差超过3倍的值 → p(|x - μ| > 3σ) ≤ 0.003
箱型图:四分位=i(n+1)/4,如果上四分位=6.75,那么上四分位=第六个值0.65+第七个值0.25;
IQR=Q3-Q1,上限Q3+1.5IQR,下限Q1-1.5IQR;
内限:Q3+1.5IQR与剔除异常值的最大值两者取小,Q1-1.5IQR与剔除异常值的最小值两者取大;
外限:Q3+3IQR与剔除异常值的最大值两者取小,Q1-3IQR与剔除异常值的最小值两者取大;
参考:https://blog.csdn.net/qq_40587575/article/details/80215776
(3)数据归一化处理:
a.标准化:(x-min)/(max-min)
b.0-1化:(x-mean)/std
比如:八个产品有两个指标AB,A权重0.6,B权重0.4,判断哪个产品综合指标最好
(4)连续数据离散化:
a.等宽法:pd.cut(ages,bins)
b.等频法:pd.qcut()
pd.cut(ages,[18,26,36,61,100],right=False)
pd.qcut(s,4)
3. 分析层:分析-洞察结论/建模分析-模型测试-迭代优化(较难)
(1) 分布分析
a.定量数据:极差=最大值-最小值,极差越大越不稳定,极差越小越稳定;
频率分布,包括频数、频率、累计频数、累计频率
方法:先定义区间分组,再画直方图,求频率.value_counts后得到频数,频率=频数/频数的总数,累计频数/累计频率.cumsum()
b.定性数据:除去极差,直接看频数频率累计频数累计频率,画直方图df[].plot(kind='bar'),画饼图plt.pie
(2)对比分析
a.绝对数比较:相减,适用于量级上差距不大。如AB产品的销量,用折线图、多元柱状图、正负堆叠图、差值折线图
多元柱状图
正负堆叠图
差值折线图
b.相对数比较:相除
aa.纵向对比:累计增长量 = 报告期水平 - 固定基期水平;逐期增长量 = 报告期水平 - 报告期前一期水平;定基增长速度=累计增长量/固定基期水平;环比增长速度=逐期增长量/报告前一期水平;
日环比=今天/昨天-1
年同比=今天/去年今天-1
bb.横向对比:同一时间不同空间,比如ABCD四个产品一周的销售量df[].plot(kind='bar')
cc.比例比较:各项与各项比较。比如:工资与消费的比例[].plot.area;
dd.结构比较:各项占总体的比重,反应总体内部结构。比如:1号产品A销售在一周内的占比;
(3)统计分析
a.集中趋势:均值、众数、中位数
b.离散趋势:极差、四分位差data.plot.box、标准差std:plt.axvline(均值-1个std)、方差var
(4)帕累托分析:将样本有大到小排序,画柱状图,求累计占比找到80%那个index:data.cumsum()/data.sum(),p[p>0.8].index[0]
帕累托
(5)正态性检验:
a.直方图:
b.QQ图:将值由小到大排序,x轴坐标(index-0.5)/n,y轴坐标(values-mean)/std;
再画一条四分位和一分为的直线,看直线是否在QQ图上;
s = pd.DataFrame(np.random.randn(1000)+10,columns = ['value'])
s.sort_values(by = 'value', inplace = True) # 重新排序
s_r = s.reset_index(drop = False) # 重新排序后,更新index
s_r['p'] = (s_r.index - 0.5) / len(s_r)
s_r['q'] = (s_r['value'] - mean) / std
st = s['value'].describe()
x1 ,y1 = 0.25, st['25%']
x2 ,y2 = 0.75, st['75%']
fig = plt.figure(figsize = (10,9))
ax3 = fig.add_subplot(3,1,3) # 创建子图3
ax3.plot(s_r['p'],s_r['value'],'k.',alpha = 0.1)
ax3.plot([x1,x2],[y1,y2],'-r')
c.K_S检验:样本数据累计频数分布f(x)和理论分布g(x)(如正态分布)比较,f(x)-g(x)最大值,p值>0.05接受f(x),p<0.05拒绝f(x)接受g(x)
步骤:(1)累计频率分布:次数、累计次数、累计频率(2)标准化取值-把非正态分布变成正态分布:(值-均值u)/std标准差(3)查阅标准正态分布,对应出理论值(4)D=累计频率-理论分布的最大值(5)所得出的最大值对照显著性对照表,求出p值是否大于0.05,若大于则满足g(x)
快速方法:
from scipy import stats
stats.kstest(df['value'], 'norm', (u, std))
# .kstest方法:KS检验,参数分别是:待检验的数据,检验方法(这里设置成norm正态分布),均值与标准差
# 结果返回两个值:statistic → D值,pvalue → P值
# p值大于0.05,为正态分布
(6)相关性分析:
a.pearson相关系数:必须满足正态分布,通过公式得到系数>0.5就相关
先通过KS检验,然后
data = pd.DataFrame({'智商':[106,86,100,101,99,103,97,113,112,110],
'每周看电视小时数':[7,0,27,50,28,29,20,12,6,17]})
data.corr()#默认pearson
data.corr(method='spearman')
b.sperman相关系数:适用于非正态分布,通过公式得到系数>0.5就相关
4. 建模层:机器学习基于python
监督学习:已知训练xy预测x的y值
(1)线型回归:
参考https://www.cnblogs.com/nxld/p/6123239.html
线型回归输入的是连续变量,输出的也是连续变量
a.散点图判断变量关系
b.拟合回归线
c.求R方检验>0.8误差小
d.预测
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(xtrain[:,np.newaxis],ytrain)#****sklearn要求输入的训练集为矩阵
xtest = np.linspace(0,10,1000)
ytest = model.predict(xtest[:,np.newaxis])
model.coef_#斜率
model.intercept_#截距
#误差检验
r2 = model.score(xtrain[:,np.newaxis],ytrain)
#R-square非常接近于1,线性回归模型拟合较好
R方图示.png
#实例:计算pizza的价格
df = pd.DataFrame({'直径':[6,8,10,14,18],
'价格':[7,9,13,17.5,18]},
index=[1,2,3,4,5])
print(df)
#画图
plt.scatter(df['直径'],df['价格'])
plt.xlim(0,20)
plt.ylim(0,20)
plt.xlabel('直径(英寸)')
plt.ylabel('价格(美元)')
plt.grid()
#构建模型:sklearn要求x为二维数组,所以会用到xtest[:,np.newaxis]或xtest.reshape(-1,1)
from sklearn.linear_model import LinearRegression
x = df['直径'].reshape(-1,1)
y = df['价格']
xtest = np.linspace(0,20,100)
model = LinearRegression()
model.fit(x,y)
pre = model.predict(xtest[:,np.newaxis])
plt.plot(xtest,pre,color='red')
print(model.coef_)#斜率
print(model.intercept_)#截距
#评估model.score
r = model.score(x,y)
print(r)#接近于1
(2)逻辑回归:
参考https://blog.csdn.net/weixin_39910711/article/details/81607386
逻辑回归输入的是连续变量,输出是分类离散变量
逻辑回归是在线性回归上套用了S函数
自我理解:(1)是S函数的内层函数(2)是LR分类器的外层函数,当有训练集xy时能求得S内层函数z的值(z>0或z<0),然后求得z>0时g(z)=1,z<0时g(z)=0,z=0时g(z)=0.5
LR2
LR3
LR4
实际应用:
from collections import OrderedDict#对字典中元素排序
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#数据集
examDict={
'学习时间':[0.5,0.75,1,1.25,1.5,1.75,1.75,2,2.25,2.5,
2.75,3,3.25,3.5,4,4.25,4.5,4.75,5,5.5],
'通过考试':[0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1]
}
examorderdict = OrderedDict(examDict)
examdf = pd.DataFrame(examorderdict)
#提取特征和标签,把学习时间作为特征属性,考试时间作为标签
exam_x = examdf['学习时间']
exam_y = examdf['通过考试']
#绘制散点图查看原始数据的分布
#plt.scatter(exam_x,exam_y)
plt.xlabel('学习时间')
plt.ylabel('是否通过考试')
#建立训练数据集和测试集:交叉验证train_test_split(样本特征,样本标签,训练数据占比)
from sklearn.cross_validation import train_test_split
xtrain,xtest,ytrain,ytest = train_test_split(exam_x,exam_y,train_size=0.8)
print(xtrain,ytrain)
print(xtest,ytest)
plt.scatter(xtrain,ytrain,color='blue',label='训练数据')
plt.scatter(xtest,ytest,color='red',label='测试数据')
plt.xlabel('学习时间')
plt.ylabel('是否通过考试')
plt.legend()
#sklearn要求输入的特征必须是二维数组
x_train = xtrain.values.reshape(-1,1)
x_test = xtest.values.reshape(-1,1)
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(x_train,ytrain)
#获取模型的概率值
p = model.predict_proba(3)
#print(p)
pre = model.predict(0)
print(pre)
#反推回归分析的函数
#斜率coef_ 截距intercept_
coef = model.coef_
inter = model.intercept_
x = 3
z = coef*x+inter
y = 1/(1+np.exp(-z))
print(y)#得到值是否大于0.5
交叉检验:建立训练集和测试集
from sklearn.cross_validation import train_test_split
xtrain,xtest,ytrain,ytest = train_test_split(exam_x,exam_y,train_size=0.8)
(3)KNN分类算法
如果一个样本在特征空间中k个最邻近的样本中大多数属于某一列,那么该样本也属于那一列。所以,KNN算法结果取决于k的选择;
思想:在训练集中数据和标签已知情况下,输入测试数据,将测试数据的特征和训练集中特征比较,找到训练集中与之最为相似的前k个数据,则该测试数据对应的类别就是k个数据中出现次数最多的那个分类。
#数据集,确定特征属性和特征标签
data = pd.DataFrame({'name':['北京遇上西雅图','喜欢你','疯狂动物城','战狼2','力王','敢死队'],
'fight':[3,2,1,101,99,98],
'kiss':[104,100,81,10,5,2],
'type':['Romance','Romance','Romance','Action','Action','Action']})
#画图
plt.scatter(data[data['type']=='Romance']['fight'],data[data['type']=='Romance']['kiss'],color='blue')
plt.scatter(data[data['type']=='Action']['fight'],data[data['type']=='Action']['kiss'],color='red')
plt.xlim(-20,120)
plt.ylim(-20,120)
plt.grid()
#预测属性
data2 = pd.DataFrame(np.random.randn(100,2)*50,columns=['kiss','fight'])
#建立KNN模型
from sklearn import neighbors
model = neighbors.KNeighborsClassifier()
model.fit(data[['fight','kiss']],data['type'])
pre = model.predict(data2[['fight','kiss']])
data2['type'] = pre
plt.scatter(data2[data2['type']=='Romance']['fight'],data2[data2['type']=='Romance']['kiss'],color='blue',marker='x')
plt.scatter(data2[data2['type']=='Action']['fight'],data2[data2['type']=='Action']['kiss'],color='red',marker='x')
print(pre)
非监督学习:无训练集直接预测x的y值
(1)关联规则Aprior
购买数据过程
(2)关联规则FP-growth
FP树
从树底部开始挖掘:
在FP-tree中以I5结尾的节点链共有两条,分别是<(I2:7),(I1:4),(I3:2),(I5:1)>和<(I2:7),(I1:4),(I5:1)>。
其中,第一条节点链表表示客户购买的物品清单<I2,I1,I3,I5>在数据库中共出现了1次。需要注意到是,尽管<I2,I4>在第一条节点链中出现了4次,单个物品<I2>出现了7次,但是它们与I5一起出现只有1次,所以在条件FP-tree中将<(I2:7),(I1:4),(I3:2),(I5:1)>记为<(I2:1),(I1:1),(I3:1),(I5:1)>。同理,第二条节点链表示客户购买的物品清单<(I2:7),(I1:4),(I5:1)>在数据库中只出现了一次。我们将p的前缀节点链<(I2:1),(I1:1),(I3:1),(I5:1)>和<(I2:1),(I1:1),(I5:1)>称为I5的条件模式基(conditional pattern base)从图可以看到I5的条件FP-tree中满足支持度阈值的剩下2个节点,所以以I5结尾的频繁项集有(I5:2),(I1,I5 :2),(I2,I5 :2),(I1,I2,I5 :2)
总结
关联规则就是从一些项集中找到关联
支持度就是出现某一项集的次数/总数;
置信度就是对于规则{Diaper}→{Beer},{Diaper, Beer}的支持度计数除于{Diaper}的支持度计数,为这个规则的置信度。例如规则{Diaper}→{Beer}的置信度为3÷3=100%。说明买了Diaper的人100%也买了Beer。
置信度confidence=P(B|A)=P(AB)/P(A),指的是发生事件A的基础上发生事件B的概率。
强关联规则:大于或等于最小支持度阈值和最小置信度阈值的规则叫做强关联规则。
区别:apriori算法多次扫描交易数据库,每次利用候选频繁集产生频繁集;而FP-growth则利用树形结构,无需产生候选频繁集而是直接得到频繁集,大大减少扫描交易数据库的次数,从而提高了算法的效率。但是apriori的算法扩展性较好,可以用于并行计算等领域
(3)K-Means聚类算法
见另一篇简书:https://www.jianshu.com/p/2d4cf11e8646
结论层
包括以下六层:
报告背景
报告目的
数据来源、数据量等基本情况
分页图表及本页结论
各部分小结和最终结论
下一步策略及趋势预测
最后分享一个自己画的脑图:
特征分析
数据处理
网友评论