一周总结

1018(周一)内容概要

主体:pandas模块结束、matplotlib模块

  • pandas其他操作补充
  • pandas实战案例
  • 可视化模块之matplotlib

周一内容详细

缺失值处理

缺失值的识别与处理
1. df.isnull 
2. df.fillna
3. df.dropna

data05 = pd.read_excel(r'data_test05.xlsx')
data05.head()
data05.isnull()  # 统计每个数据项是否有缺失
data05.isnull().any(axis = 0)  # 统计列字段下是否含有缺失
# 计算各列数据的缺失比例
data05.isnull().sum(axis = 0)/data05.shape[0]
data05.dropna()

data05.fillna(value=0)  # 将所有的缺失值填充为0(不合理)
# 针对不同的缺失值使用合理的填充手段
data05.fillna(value = {
  'gender':data05.gender.mode()[0],  # 众数:可以有一个也可能是多个
  'age':data05.age.mean(),  # 平均值
  'income':data05.income.median()  # 中位数
}, inplace = True)

数据汇总

# 透视表功能
pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')

data:指定需要构造透视表的数据集 
values:指定需要拉入“数值”框的字段列表
index:指定需要拉入“行标签”框的字段列表 
columns:指定需要拉入“列标签”框的字段列表 
aggfunc:指定数值的统计函数,默认为统计均值,也可以指定numpy模块中的其他统计函数 

fill_value:指定一个标量,用于填充缺失值 
margins:bool类型参数,是否需要显示行或列的总计值,默认为False 
dropna:bool类型参数,是否需要删除整列为缺失的字段,默认为True 
margins_name:指定行或列的总计名称,默认为All
  
data06 = pd.read_csv(r'diamonds.csv')
data06.head()

pd.pivot_table(data06, index = 'color', values='price', aggfunc='mean')
pd.pivot_table(data06, index = 'color', columns='clarity', values='price', aggfunc='size')

分组与聚合

import numpy as np
# 通过groupby方法,指定分组变量
grouped = data06.groupby(by = ['color','cut'])
# 对分组变量进行统计汇总
result = grouped.aggregate({'color':np.size, 'carat':np.min, 
                            'price':np.mean, 'table':np.max})



# 调整变量名的顺序
result = pd.DataFrame(result, columns=['color','carat','price','table'])


# 数据集重命名
result.rename(columns={'color':'counts',
                       'carat':'min_weight',
                       'price':'avg_price',
                       'table':'max_table'}, 
              inplace=True)

练习题

# 分析NBA各球队冠军次数及球员FMVP次数
res = pd.read_html('https://baike.baidu.com/item/NBA%E6%80%BB%E5%86%A0%E5%86%9B/2173192?fr=aladdin')  ### 返回的是一个列表  列表中是当前页面的所有表格数据
type(res)
res

# 获取有效数据
champion = res[0]
champion

# 处理列字段名称
drop方法使用

# 针对冠军字段分组
champion.groupby('冠军').groups

# 获取分组之后的各分组大小
champion.groupby('冠军').size()
# 获取各组冠军次数
champion.groupby('冠军').size().sort_values(ascending=False)  # 升序

# 分组字段可以一次性取多个
champion.groupby(['冠军', 'FMVP']).size()

数据的合并

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None)

objs:指定需要合并的对象,可以是序列、数据框或面板数据构成的列表 
axis:指定数据合并的轴,默认为0,表示合并多个数据的行,如果为1,就表示合并多个数据的列
join:指定合并的方式,默认为outer,表示合并所有数据,如果改为inner,表示合并公共部分的数据 
join_axes:合并数据后,指定保留的数据轴 
ignore_index:bool类型的参数,表示是否忽略原数据集的索引,默认为False,如果设为True,就表示忽略原索引并生成新索引
keys:为合并后的数据添加新索引,用于区分各个数据部分
  
  
# 构造数据集df1和df2
df1 = pd.DataFrame({
  'name':['张三','李四','王二'], 
  'age':[21,25,22], 
  'gender':['男','女','男']}
)
df2 = pd.DataFrame({
  'name':['丁一','赵五'], 
  'age':[23,22], 
  'gender':['女','女']}
)
# 数据集的纵向合并
pd.concat([df1,df2] , keys = ['df1','df2'])  # 加keys参数可以在合并之后看到数据来源

pd.concat([df1,df2] , keys = ['df1','df2']).reset_index() 


pd.concat([df1,df2] , keys = ['df1','df2']).reset_index().drop(labels ='level_1', axis = 1).rename(columns = {'level_0':'Class'})



# 如果df2数据集中的“姓名变量为Name”
df2 = pd.DataFrame({
  'Name':['丁一','赵五'], 
  'age':[23,22], 
  'gender':['女','女']}
)
# 数据集的纵向合并
pd.concat([df1,df2])
# concat行合并,数据源的变量名称完全相同(变量名顺序没有要求)

数据的连接

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'))

left:指定需要连接的主 right:指定需要连接的辅表
how:指定连接方式,默认为inner内连,还有其他选项,如左连left、右连right和外连outer on:指定连接两张表的共同字段
left_on:指定主表中需要连接的共同字段
right_on:指定辅表中需要连接的共同字段 
left_index:bool类型参数,是否将主表中的行索引用作表连接的共同字段,默认为False right_index:bool类型参数,是否将辅表中的行索引用作表连接的共同字段,默认为False sort:bool类型参数,是否对连接后的数据按照共同字段排序,默认为False 
suffixes:如果数据连接的结果中存在重叠的变量名,则使用各自的前缀进行区分
  
  
# 构造数据集
df3 = pd.DataFrame({
  'id':[1,2,3,4,5],
  'name':['张三','李四','王二','丁一','赵五'],
  'age':[27,24,25,23,25],
  'gender':['男','男','男','女','女']})
df4 = pd.DataFrame({
  'Id':[1,2,2,4,4,4,5], 
  'score':[83,81,87,75,86,74,88], 
  'kemu':['科目1','科目1','科目2','科目1','科目2','科目3','科目1']})
df5 = pd.DataFrame({
  'id':[1,3,5],
  'name':['张三','王二','赵五'],
  'income':[13500,18000,15000]})

# 首先df3和df4连接
merge1 = pd.merge(left = df3, 
                  right = df4, 
                  how = 'left', 
                  left_on='id', 
                  right_on='Id')
# 再将连接结果与df5连接
merge2 = pd.merge(left = merge1, 
                  right = df5, 
                  how = 'left')

简介

是一个强大的python绘图和数据可视化工具包,数据可视化也是我们数据分析重要环节之一,可以帮助我们分析出很多价值信息,也是数据分析的最后一个可视化阶段

下载

# python纯开发环境下
pip3 install matplotlib
# anaconda环境下
conda install matplotlib
'''anaconda已经自动帮助我们下载好了数据分析相关的模块,其实无需我们再下载'''

导入

import matplotlib.pyplot as plt

课程目标

1. 离散型数据的可视化 
2. 连续性数据的可视化 
3. 关系型数据的可视化 
4. 多图形的组合

饼图的绘制

饼图属于最传统的统计图形之一,几乎随处可见,例如大型公司的屏幕墙、各种年度论坛的演示稿以及各大媒体发布的数据统计报告等;
饼图是将一个圆分割成不同大小的楔(扇)形,而圆中的每一个楔形代表了不同的类别值,通常根据楔形的面积大小来判断类别值的差异;

pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, labeldistance=1.1)

x:指定绘图的数据 
explode:指定饼图某些部分的突出显示,即呈现爆炸式
labels:为饼图添加标签说明,类似于图例说明 
colors:指定饼图的填充色 
autopct:自动添加百分比显示,可以采用格式化的方法显示 
pctdistance:设置百分比标签与圆心的距离 
labeldistance:设置各扇形标签(图例)与圆心的距离
  
# 导入第三方模块
import matplotlib.pyplot as plt
# 解决中文乱码情况
plt.rcParams['font.sans-serif'] = ['SimHei']
# 构造数据
edu = [0.2515,0.3724,0.3336,0.0368,0.0057]
labels = ['中专','大专','本科','硕士','其他']
explode = [0,0.1,0,0,0]
# 绘制饼图                                                                              plt.axes(aspect='equal')  # 如果python版本较低可能是扁的需要加该代码   
plt.pie(x = edu,  # 绘图数据
        labels=labels,  # 添加教育水平标签
        autopct='%.1f%%',  # 设置百分比的格式,这里保留一位小数
        explode = explode
       )
# 显示图形
plt.show()

条形图的绘制

虽然饼图可以很好地表达离散型变量在各水平上的差异,但其不擅长对比差异不大或水平值过多的离散型变量,因为饼图是通过各扇形面积的大小来比价差异的,面积的比较有时并不直观;
对于条形图而言,对比的是柱形的高低,柱体越高,代表的数值越大,反之亦然;

bar(x, height, width=0.8, bottom=None, color=None, edgecolor=None, tick_label=None, label = None, ecolor=None)

x:传递数值序列,指定条形图中x轴上的刻度值 
height:传递数值序列,指定条形图y轴上的高度
width:指定条形图的宽度,默认为0.8 
bottom:用于绘制堆叠条形图 
color:指定条形图的填充色 
edgecolor:指定条形图的边框色 
tick_label:指定条形图的刻度标签 
label:指定条形图的标签,一般用以添加图例
  
 
'''垂直条形图'''
import pandas as pd
# 读入数据
GDP = pd.read_excel(r'Province GDP 2017.xlsx')

# 设置绘图风格(不妨使用R语言中的ggplot2风格)
plt.style.use('ggplot')
# 绘制条形图
plt.bar(x = range(GDP.shape[0]), # 指定条形图x轴的刻度值
        height = GDP.GDP, # 指定条形图y轴的数值
        tick_label = GDP.Province, # 指定条形图x轴的刻度标签
        color = 'steelblue', # 指定条形图的填充色
       )
# 添加y轴的标签
plt.ylabel('GDP(万亿)')
# 添加条形图的标题
plt.title('2017年度6个省份GDP分布')
# 为每个条形图添加数值标签
for x,y in enumerate(GDP.GDP):
    plt.text(x,y+0.1,'%s' %round(y,1),ha='center')
# 显示图形    
plt.show()

1019(周二)内容概要

主体:matplotlib结束、数据清洗

  • 水平条形图
  • 交叉条形图
  • 散点图与气泡图
  • 热力图
  • 箱线图
  • 图形可视化其他模块补充
  • 数据清洗

周二内容详细

条形图的绘制

虽然饼图可以很好地表达离散型变量在各水平上的差异,但其不擅长对比差异不大或水平值过多的离散型变量,因为饼图是通过各扇形面积的大小来比价差异的,面积的比较有时并不直观;
对于条形图而言,对比的是柱形的高低,柱体越高,代表的数值越大,反之亦然;

bar(x, height, width=0.8, bottom=None, color=None, edgecolor=None, tick_label=None, label = None, ecolor=None)

x:传递数值序列,指定条形图中x轴上的刻度值 
height:传递数值序列,指定条形图y轴上的高度
width:指定条形图的宽度,默认为0.8 
bottom:用于绘制堆叠条形图 
color:指定条形图的填充色 
edgecolor:指定条形图的边框色 
tick_label:指定条形图的刻度标签 
label:指定条形图的标签,一般用以添加图例
  
 
'''垂直条形图'''
import pandas as pd
# 读入数据
GDP = pd.read_excel(r'Province GDP 2017.xlsx')

# 设置绘图风格(不妨使用R语言中的ggplot2风格)
plt.style.use('ggplot')
# 绘制条形图
plt.bar(x = range(GDP.shape[0]), # 指定条形图x轴的刻度值
        height = GDP.GDP, # 指定条形图y轴的数值
        tick_label = GDP.Province, # 指定条形图x轴的刻度标签
        color = 'steelblue', # 指定条形图的填充色
       )
# 添加y轴的标签
plt.ylabel('GDP(万亿)')
# 添加条形图的标题
plt.title('2017年度6个省份GDP分布')
# 为每个条形图添加数值标签
for x,y in enumerate(GDP.GDP):
    plt.text(x,y+0.1,'%s' %round(y,1),ha='center')
# 显示图形    
plt.show()


'''水平条形图'''
# 对读入的数据做升序排序
GDP.sort_values(by = 'GDP', inplace = True)
# 绘制条形图
plt.barh(y = range(GDP.shape[0]), # 指定条形图y轴的刻度值
        width = GDP.GDP, # 指定条形图x轴的数值
        tick_label = GDP.Province, # 指定条形图y轴的刻度标签
        color = 'steelblue', # 指定条形图的填充色
       )
# 添加x轴的标签
plt.xlabel('GDP(万亿)')
# 添加条形图的标题
plt.title('2017年度6个省份GDP分布')
# 为每个条形图添加数值标签
for y,x in enumerate(GDP.GDP):
    plt.text(x+0.1,y,'%s' %round(x,1),va='center')
# 显示图形    
plt.show()


'''交叉条形图'''
HuRun = pd.read_excel('HuRun.xlsx')
# Pandas模块之水平交错条形图
HuRun_reshape = HuRun.pivot_table(index = 'City', columns='Year',
values='Counts').reset_index()
# 对数据集降序排序
HuRun_reshape.sort_values(by = 2016, ascending = False, inplace = True)
HuRun_reshape.plot(x = 'City', y = [2016,2017], kind = 'bar', 
color = ['steelblue', 'indianred'], 
                              # 用于旋转x轴刻度标签的角度,0表示水平显示刻度标签
                   	rot = 0, 
                   	width = 0.8, title = '近两年5个城市亿万资产家庭数比较')

# 添加y轴标签
plt.ylabel('亿万资产家庭数')
plt.xlabel('')
plt.show()

直方图的绘制

直方图一般用来观察数据的分布形态,横坐标代表数值的均匀分段,纵坐标代表每个段内的观测数量(频数);
一般直方图都会与核密度图搭配使用,目的是更加清晰地掌握数据的分布特征;

plt.hist(x, bins=10, normed=False, orientation='vertical', color=None, label=None)
x:指定要绘制直方图的数据。 
bins:指定直方图条形的个数。
normed:是否将直方图的频数转换成频率
orientation:设置直方图的摆放方向,默认为垂直方向 
color:设置直方图的填充色 
edgecolor:设置直方图边框色 
label:设置直方图的标签,可通过legend展示其图例
  
  
  
Titanic = pd.read_csv('titanic_train.csv')

# 检查年龄是否有缺失(如果数据中存在缺失值,将无法绘制直方图)
any(Titanic.Age.isnull())
# 不妨删除含有缺失年龄的观察
Titanic.dropna(subset=['Age'], inplace=True)
# 绘制直方图
plt.hist(x = Titanic.Age, # 指定绘图数据
         bins = 20, # 指定直方图中条块的个数
         color = 'steelblue', # 指定直方图的填充色
         edgecolor = 'black' # 指定直方图的边框色
         )
# 添加x轴和y轴标签
plt.xlabel('年龄')
plt.ylabel('频数')
# 添加标题
plt.title('乘客年龄分布')
# 显示图形
plt.show()

箱线图的绘制

箱线图是另一种体现数据分布的图形,通过该图可以得知数据的下须值(Q1-1.5IQR)、下四 分位数(Q1)、中位数(Q2)、均值、上四分位(Q3)数和上须值(Q3+1.5IQR),更重要的是,箱线图还可以发现数据中的异常点;

plt.boxplot(x, vert=None, whis=None, patch_artist=None, meanline=None, showmeans=None, showcaps=None, showbox=None, showfliers=None, boxprops=None, labels=None, flierprops=None, medianprops=None, meanprops=None, capprops=None, whiskerprops=None)

x:指定要绘制箱线图的数据 
vert:是否需要将箱线图垂直摆放,默认垂直摆放
whis:指定上下须与上下四分位的距离,默认为1.5倍的四分位差 
patch_artist:bool类型参数,是否填充箱体的颜色;默认为False 
meanline:bool类型参数,是否用线的形式表示均值,默认为False 
showmeans:bool类型参数,是否显示均值,默认为False 
showcaps:bool类型参数,是否显示箱线图顶端和末端的两条线(即上下须),默认为True showbox:bool类型参数,是否显示箱线图的箱体,默认为True
showfliers:是否显示异常值,默认为True 
boxprops:设置箱体的属性,如边框色,填充色等
labels:为箱线图添加标签,类似于图例的作用 
filerprops:设置异常值的属性,如异常点的形状、大小、填充色等 
medianprops:设置中位数的属性,如线的类型、粗细等 
meanprops:设置均值的属性,如点的大小、颜色等 
capprops:设置箱线图顶端和末端线条的属性,如颜色、粗细等 
whiskerprops:设置须的属性,如颜色、粗细、线的类型等
  
  
Sec_Buildings = pd.read_excel('sec_buildings.xlsx')
# 绘制箱线图
plt.boxplot(x = Sec_Buildings.price_unit, # 指定绘图数据
            patch_artist=True, # 要求用自定义颜色填充盒形图,默认白色填充
            showmeans=True, # 以点的形式显示均值
            boxprops = {'color':'black','facecolor':'steelblue'},# 设置箱体属性,如边框色和填充色
            # 设置异常点属性,如点的形状、填充色和点的大小
            flierprops = {'marker':'o','markerfacecolor':'red', 'markersize':3,'markeredgecolor':'red'}, 
            # 设置均值点的属性,如点的形状、填充色和点的大小
            meanprops = {'marker':'D','markerfacecolor':'indianred', 'markersize':4}, 
            # 设置中位数线的属性,如线的类型和颜色
            medianprops = {'linestyle':'--','color':'orange'}, 
            labels = [''] # 删除x轴的刻度标签,否则图形显示刻度标签为1
           )
# 添加图形标题
plt.title('二手房单价分布的箱线图')
# 显示图形
plt.show()

折线图的绘制

对于时间序列数据而言,一般都会使用折线图反映数据背后的趋势。通常折线图的横坐标指代日期数据,纵坐标代表某个数值型变量,当然还可以使用第三个离散变量对折线图进行分组处理;

plt.plot(x, y, linestyle, linewidth, color, marker,markersize, markeredgecolor, markerfactcolor,markeredgewidth, label, alpha)

x:指定折线图的x轴数据 
y:指定折线图的y轴数据
linestyle:指定折线的类型,可以是实线、虚线、点虚线、点点线等,默认为实线 
linewidth:指定折线的宽度 
marker:可以为折线图添加点,该参数是设置点的形状 
markersize:设置点的大小
markeredgecolor:设置点的边框色 
markerfactcolor:设置点的填充色 
markeredgewidth:设置点的边框宽度 
label:为折线图添加标签,类似于图例的作用
  
  
%matplotlib  # 以弹框的形式显示图形
# 数据读取
wechat = pd.read_excel(r'wechat.xlsx')
# 绘制单条折线图
plt.plot(wechat.Date, # x轴数据
         wechat.Counts, # y轴数据
         linestyle = '-', # 折线类型
         linewidth = 2, # 折线宽度
         color = 'steelblue', # 折线颜色
         marker = 'o', # 折线图中添加圆点
         markersize = 6, # 点的大小
         markeredgecolor='black', # 点的边框色
         markerfacecolor='brown') # 点的填充色
# 获取图的坐标信息
ax = plt.gca()
# 设置日期的显示格式  
date_format = mpl.dates.DateFormatter("%m-%d")  
ax.xaxis.set_major_formatter(date_format) 
# 设置x轴每个刻度的间隔天数
xlocator = mpl.ticker.MultipleLocator(7)
ax.xaxis.set_major_locator(xlocator)
# 添加y轴标签
plt.ylabel('人数')
# 添加图形标题
plt.title('每天微信文章阅读人数趋势')
# 显示图形
plt.show()


# 绘制两条折线图
# 导入模块,用于日期刻度的修改
import matplotlib as mpl
# 绘制阅读人数折线图
plt.plot(wechat.Date, # x轴数据
         wechat.Counts, # y轴数据
         linestyle = '-', # 折线类型,实心线
         color = 'steelblue', # 折线颜色
         label = '阅读人数'
         )
# 绘制阅读人次折线图
plt.plot(wechat.Date, # x轴数据
         wechat.Times, # y轴数据
         linestyle = '--', # 折线类型,虚线
         color = 'indianred', # 折线颜色
         label = '阅读人次'
         )
# 获取图的坐标信息
ax = plt.gca()
# 设置日期的显示格式  
date_format = mpl.dates.DateFormatter("%m-%d")  
ax.xaxis.set_major_formatter(date_format) 
# 设置x轴显示多少个日期刻度
# xlocator = mpl.ticker.LinearLocator(10)
# 设置x轴每个刻度的间隔天数
xlocator = mpl.ticker.MultipleLocator(7)
ax.xaxis.set_major_locator(xlocator)
# 为了避免x轴刻度标签的紧凑,将刻度标签旋转45度
plt.xticks(rotation=45)

# 添加y轴标签
plt.ylabel('人数')
# 添加图形标题
plt.title('每天微信文章阅读人数与人次趋势')
# 添加图例
plt.legend()
# 显示图形
plt.show()

散点图的绘制

如果需要研究两个数值型变量之间是否存在某种关系,例如正向的线性关系,或者是趋势性的非线性关系,那么散点图将是最佳的选择;

scatter(x, y, s=20, c=None, marker='o', alpha=None, linewidths=None, edgecolors=None) 
x:指定散点图的x轴数据
y:指定散点图的y轴数据 
s:指定散点图点的大小,默认为20,通过传入其他数值型变量,可以实现气泡图的绘制 
c:指定散点图点的颜色,默认为蓝色,也可以传递其他数值型变量,通过cmap参数的色阶表示数值大小
marker:指定散点图点的形状,默认为空心圆
alpha:设置散点的透明度
linewidths:设置散点边界线的宽度
edgecolors:设置散点边界线的颜色
  
# 读入数据
iris = pd.read_csv(r'iris.csv')
# 绘制散点图
plt.scatter(x = iris.Petal_Width, # 指定散点图的x轴数据
            y = iris.Petal_Length, # 指定散点图的y轴数据
            color = 'steelblue' # 指定散点图中点的颜色
           )

# 添加x轴和y轴标签
plt.xlabel('花瓣宽度')
plt.ylabel('花瓣长度')
# 添加标题
plt.title('鸢尾花的花瓣宽度与长度关系')
# 显示图形
plt.show()

气泡图的绘制

气泡图的实质就是通过第三个数值型变量控制每个散点的大小,点越大,代表的第三维数值越高,反之亦然;
气泡图的绘制,使用的仍然是scatter函数,区别在于函数的s参数被赋予了具体的数值型变量;

热力图的绘制

热力图也称为交叉填充表,图形最典型的用法就是实现列联表的可视化,即通过图形的方式展现两个离散变量之间的组合关系;

# matplotlib绘制热力图不太方便需要借助于seaborn模块
sns.heatmap(data, cmap=None, annot=None, fmt='.2g', annot_kws=None, linewidths=0, linecolor ='white)
            
data:指定绘制热力图的数据集 
cmap:指定一个colormap对象,用于热力图的填充色
annot:指定一个bool类型的值或与data参数形状一样的数组,如果为True,就在热力图的每个单元上显示数值 
fmt:指定单元格中数据的显示格式
annot_kws:有关单元格中数值标签的其他属性描述,如颜色、大小等 
linewidths:指定每个单元格的边框宽度 
linecolor:指定每个单元格的边框颜色
            
import numpy as np
import seaborn as sns
# 读取数据
Sales = pd.read_excel(r'Sales.xlsx')
# 根据交易日期,衍生出年份和月份字段
Sales['year'] = Sales.Date.dt.year
Sales['month'] = Sales.Date.dt.month
# 统计每年各月份的销售总额(绘制热力图之前,必须将数据转换为交叉表形式)
Summary = Sales.pivot_table(index = 'month', columns = 'year', values = 'Sales', aggfunc = np.sum)
Summary
# 绘制热力图
sns.heatmap(data = Summary, # 指定绘图数据
            cmap = 'PuBuGn', # 指定填充色
            linewidths = .1, # 设置每个单元格边框的宽度
            annot = True, # 显示数值
            fmt = '.1e' # 以科学计算法显示数据
            )
#添加标题
plt.title('每年各月份销售总额热力图')
# 显示图形
plt.show()

组合图的绘制

工作中往往会根据业务需求,将绘制的多个图形组合到一个大图框内,形成类似仪表板的效果;
plt.subplot2grid(shape, loc, rowspan=1, colspan=1, **kwargs)

shape:指定组合图的框架形状,以元组形式传递,如2×3的矩阵可以表示成(2,3) 
loc:指定子图所在的位置,如shape中第一行第一列可以表示成(0,0) 
rowspan:指定某个子图需要跨几行
colspan:指定某个子图需要跨几列

"""
# 设置大图框的长和高 plt.figure(figsize = (12,6))
# 设置第一个子图的布局
ax1 = plt.subplot2grid(shape = (2,3), loc = (0,0))
# 设置第二个子图的布局
ax2 = plt.subplot2grid(shape = (2,3), loc = (0,1))
# 设置第三个子图的布局
ax3 = plt.subplot2grid(shape = (2,3), loc = (0,2), rowspan = 2)
# 设置第四个子图的布局
ax4 = plt.subplot2grid(shape = (2,3), loc = (1,0), colspan = 2)
"""

# 读取数据
Prod_Trade = pd.read_excel(r'Prod_Trade.xlsx')
# 衍生出交易年份和月份字段
Prod_Trade['year'] = Prod_Trade.Date.dt.year
Prod_Trade['month'] = Prod_Trade.Date.dt.month

# 设置大图框的长和高
plt.figure(figsize = (12,6))
# 设置第一个子图的布局
ax1 = plt.subplot2grid(shape = (2,3), loc = (0,0))
# 统计2012年各订单等级的数量
Class_Counts = Prod_Trade.Order_Class[Prod_Trade.year == 2012].value_counts()
Class_Percent = Class_Counts/Class_Counts.sum()
# 绘制订单等级饼图
ax1.pie(x = Class_Percent.values, labels = Class_Percent.index, autopct = '%.1f%%')
# 添加标题
ax1.set_title('各等级订单比例')

# 设置第二个子图的布局
ax2 = plt.subplot2grid(shape = (2,3), loc = (0,1))
# 统计2012年每月销售额
Month_Sales = Prod_Trade[Prod_Trade.year == 2012].groupby(by = 'month').aggregate({'Sales':np.sum})
# 绘制销售额趋势图
Month_Sales.plot(title = '2012年各月销售趋势', ax = ax2, legend = False)
# 删除x轴标签
ax2.set_xlabel('')

# 设置第三个子图的布局
ax3 = plt.subplot2grid(shape = (2,3), loc = (0,2), rowspan = 2)
# 绘制各运输方式的成本箱线图
sns.boxplot(x = 'Transport', y = 'Trans_Cost', data = Prod_Trade, ax = ax3)
# 添加标题
ax3.set_title('各运输方式成本分布')
# 删除x轴标签
ax3.set_xlabel('')
# 修改y轴标签
ax3.set_ylabel('运输成本')

# 设置第四个子图的布局
ax4 = plt.subplot2grid(shape = (2,3), loc = (1,0), colspan = 2)
# 2012年客单价分布直方图
sns.distplot(Prod_Trade.Sales[Prod_Trade.year == 2012], bins = 40, norm_hist = True, ax = ax4, hist_kws = {'color':'steelblue'}, kde_kws=({'linestyle':'--', 'color':'red'}))
# 添加标题
ax4.set_title('2012年客单价分布图')
# 修改x轴标签
ax4.set_xlabel('销售额')

# 调整子图之间的水平间距和高度间距
plt.subplots_adjust(hspace=0.6, wspace=0.3)
# 图形显示
plt.show()

可视化相关模块

1.matplotlib
2.seaborn
3.highcharts
4.echarts
	pyecharts  # 可以通过python代码直接调用
5.ds.js
"""只要python学的好 很多领域都有用武之地"""

1020(周三)内容概要

主体:数据清洗(数据分析之前对数据进行各项处理以达到分析的要求)

  • 数据清洗的概念

  • 数据清洗实战案例

    旅游数据的清洗
    

周三内容详细

数据清洗的概念

# 类比定义
数据分析过程							做菜过程
	明确需求							明确做什么菜品
    收集采集							去菜市场买菜
    数据清洗							洗菜切菜配菜
    数据分析							炒菜
    数据报告 + 数据可视化				 拍照发朋友圈吃菜
    
# 专业定义
	数据清洗是从记录表、表格、数据库中检测、纠正或删除损坏或不准确记录的过程
    
# 专业名词
	脏数据
    	没有经过处理自身含有一定问题的数据(缺失、异常、重复...)
    干净数据
    	经过处理完全符合规范要求的数据
        
# 常用方法
	1.读取外部数据
    	read_csv read_excel read_sql read_html
     2.数据概览
    	index columns head tail shape describe info dtypes
     3.简单处理
    	移除首尾空格 大小写转换...
     4.重复值处理
    	duplicated()查看是否含有重复数据
        drop_duplicates()删除重复数据
     5.缺失值处理
    	删除缺失值、填充缺失值
     6.异常值处理
    	删除异常值、修正异常值(当作缺失值处理)
     7.字符串处理
    	切割、筛选...
     8.时间格式处理
    	Y m d H M S
     '''步骤3到8没有固定的顺序 只不过前期不熟练的情况下可以如此执行'''

数据概览

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv(r'qunar_freetrip.csv')
# 1.查看前五条数据 掌握大概
df.head()
# 2.查看表的行列总数
df.shape
# 3.查看所有的列字段
df.columns  # 发现列字段有一些是有空格的
# 4.查看数据整体信息
df.info()  # 发现去程时间和回程时间是字符串类型需要做日期类型转换
# 5.快速统计
df.describe()

df.columns

列字段处理

# 1.删除无用列字段
# df.drop(columns='Unnamed: 0',axis=1,inplace=True)
# 2.获取列字段
cols = df.columns.values
# 3.for循环依次取出列字段首位的空格
# 方式1 比较繁琐
# ccs = []
# for col in cols:
#     ccs.append(col.strip())
# print(ccs)
# 方式2 列表生成式
df.columns = [col.strip() for col in cols]

重复值处理

# 4.重复数据查找
# df.duplicated()
# 5.简单的楼一眼重复数据的模样(布尔值索引)  可以省略
# df[df.duplicated()]
# 6.针对重复的数据 一般情况下都是直接删除的
# df.drop_duplicates(inplace=True)
# 7.确认是否删除
# df.shape
# 8.行索引会不会因为数据的删除而自动重置(删除完数据之后行索引是不会自动重置的)
## 如何获取表的行索引值
# df.index
## 右侧加上赋值符号就是修改行索引值
# df.index = range(0,df.shape[0])
df.tail()

异常值处理

# 利用快速统计大致筛选出可能有异常数据的字段
# df.describe()  # 价格小于节省 那么可能是价格有问题或者节省有问题

# 利用公式求证我们的猜想
sd = (df['价格'] - df['价格'].mean()) / df['价格'].std()  # 判断的标准
# 利用逻辑索引筛选数据
df[(sd > 3)|(sd < -3)]
# 利用绝对值
df[abs(sd) > 3]  # abs就是绝对值的意思(移除正负号)

# 同理验证节省是否有异常(不一定要使用)
# sd1 = (df['节省'] - df['节省'].mean()) / df['节省'].std()  # 判断的标准
# 利用逻辑索引筛选数据
# df[(sd > 3)|(sd < -3)]
# 利用绝对值
# df[abs(sd1) > 3]  # abs就是绝对值的意思(移除正负号)


# 直接简单粗暴找节省大于价格的数据(推荐下列方式)
df[df['节省'] > df['价格']]



# 删除价格和节省都有异常的数据
# 方式1:先拼接 再一次性删除
# 横向合并pd.merge()
# 纵向合并pd.concat()
# res = pd.concat([df[df['节省'] > df['价格']],df[abs(sd) > 3]])
## 获取要删除的行数据 索引值
# del_index = res.index
# 根据索引删除数据
df.drop(index=del_index,inplace=True)
# 再次重置索引
df.index = range(0,df.shape[0])
# 方式2: 得出一个结果就删一个

出发地缺失值处理

# 查找具有缺失值的列名称
df.isnull().sum()  # 统计每个字段缺失数据条数

# 利用布尔值索引筛选出出发地有缺失的数据
df[df.出发地.isnull()]  

# 获取出发地缺失的数据的路线数据
df.loc[df.出发地.isnull(),'路线名'].values


# 利用字符串切割替换出发地缺失数据
df.loc[df.出发地.isnull(),'出发地'] = [i.split('-')[0] for i in df.loc[df.出发地.isnull(),'路线名'].values]
################################
# 操作数据的列字段需要使用loc方法
################################
# 针对缺失值的处理
#     1.采用数学公式依据其他数据填充
#     2.缺失值可能在其他单元格中含有
#     3.如果缺失值数量展示很小可删除
# '''

目的地缺失值处理

# 针对目的地操作如上(筛选要比出发地难!!!)
# df[df.目的地.isnull()]  
# 获取目的地缺失的路线数据
# df.loc[df.目的地.isnull(),'路线名'].values
# 利用正则筛选出目的地
import re
# 案例演示
reg_exp = '-(.*?)\d'
# res = re.findall(reg_exp,'深圳-秦皇岛3天2晚 | 入住大连黄金山大酒店 + 南方航空/东海往返机票')

df.loc[df.目的地.isnull(),'目的地'] = [re.findall(reg_exp,i) for i in df.loc[df.目的地.isnull(),'路线名'].values]

作业讲解之缺失值处理

## 计算缺失数据占比
df.isnull().sum()/df.shape[0]  # 我们自己规定占比小于0.1%可以直接删除

"""
针对缺失数据有几种处理方式
    1.占比过小可以直接删除
    2.利用均值、统一值直接填充
    3.根据不同的情况采用不同的计算公式填充
常用的四个方法    
    isnull
    notnull
    fillna
    dropna
保留几位小数
    round(数据,保留几位)
"""
# 筛选出所有价格缺失的数据
# df[df['价格'].isnull()]
# 直接利用价格的均值填充缺失数据
df['价格'].mean()  # 1732.5140901771338
round(df['价格'].mean(),1)
df['价格'].fillna(round(df['价格'].mean(),1),inplace=True)

# 同理针对节省的数据也做中位数填充(其实应该结合实际采用不同的方法)
df['节省'].fillna(round(df['节省'].mean(),1),inplace=True)

# 验证
df.isnull().sum()

补充

"""MySQL中如何快速判断某列是否含有重复的数据"""
# 思路:就是统计某个字段下数据的个数  在利用去重操作 两者结合判断
select count(name) from userinfo;
select count(distinct(name)) from userinfo;
# 如果两者数字相同表示name列没有重复的数据 不同表示含有重复的数据

1021(周四)内容详细

线性回归模型

重要名词解释

# 数据符号网站
# 因变量与自变量
# 哑变量

# 如何判断两个变量之间是否存在线性关系与非线性关系
	1.散点图
    2.公式计算
    	大于等于0.8表示高度相关
        绝对值大于等于0.5小于等于0.8表示中度相关
        绝对值大于等于0.3小于0.5表示弱相关
        绝对值小于0.3表示几乎不相关(需要注意这里的不相干指的是没有线性关系 可能两者之间有其他关系)
	    import numpy
        import pandas
        X = [52,19,7,33,2]
        Y = [162,61,22,100,6]
        # 1.公式计算#均值
        XMean = numpy.mean(X)
        YMean = numpy.mean(Y)
        # 标准差
        XSD = numpy.std(X)
        YSD = numpy.std(Y)
        # z分数
        ZX = (X-XMean)/XSD
        ZY = (Y-YMean)/YSD  
        # 相关系数
        r = numpy.sum(ZX*ZY)/(len(X))
        # 2.numpy中的corrcoef方法直接计算
        t=numpy.corrcoef(X,Y)
        # 3.pandas中的corr方法直接计算
        data = pandas.DataFrame({'X':X,'Y':Y})
        t2=data.corr()
        
        
# 训练集与测试集
	训练集用于模型的训练创建  测试集用于模型的测试检验
    一般情况下训练集占总数据的80%、测试集占总数占20%
 
# 哑变量
	在生成算法模型的时候有些变量可能并不是数字无法直接带入公式计算
    此时可以构造哑变量 >>> C(State)

自定义哑变量

# 生成由State变量衍生的哑变量
dummies = pd.get_dummies(Profit.State)
# 将哑变量与原始数据集水平合并
Profit_New = pd.concat([Profit,dummies], axis = 1)
# 删除State变量和California变量(因为State变量已被分解为哑变量,New York变量需要作为参照组)
Profit_New.drop(labels = ['State','New York'], axis = 1, inplace = True)
# 拆分数据集Profit_New
train, test = model_selection.train_test_split(Profit_New, test_size = 0.2, random_state=1234)
# 建模
model2 = sm.formula.ols('Profit~RD_Spend+Administration+Marketing_Spend+Florida+California', data = train).fit()
print('模型的偏回归系数分别为:\n', model2.params)

1022(周五)内容概要

  • 模型的假设检验(F与T)

  • 岭回归与Lasso回归

    主要是用来解决线性回归模型的不足之处
    
  • Logistic回归模型

  • 决策树与随机森林

  • K近邻模型

周五内容详细

模型的假设检验(F与T)

'''
F检验:提出原假设和备择假设 之后计算统计量与理论值 最后比较
	F检验主要检验的是模型是否合理
'''
# 导⼊第三⽅模块
import numpy as np
# 计算建模数据中因变量的均值
ybar=train.Profit.mean()
# 统计变量个数和观测个数
p=model2.df_model
n=train.shape[0]
# 计算回归离差平⽅和
RSS=np.sum((model2.fittedvalues-ybar)**2)
# 计算误差平⽅和
ESS=np.sum(model2.resid**2)
# 计算F统计量的值
F=(RSS/p)/(ESS/(n-p-1))
print('F统计量的值:',F)
F统计量的值:174.6372
    
# 导⼊模块
from scipy.stats import f
# 计算F分布的理论值
F_Theroy = f.ppf(q=0.95, dfn = p,dfd = n-p-1)
print('F分布的理论值为:',F_Theroy)
out:
F分布的理论值为: 2.5026
'''
计算出来的F统计量值174.64远远⼤于F分布的理论值2.50
所以应当拒绝原假设(先假设模型不合理)
'''

T检验

"""T检验更加侧重于检验模型的各个参数是否合理"""
model.summary()  # 绝对值越小影响越大

线性回归模型的短板

#############################################
1.自变量的个数大于样本量
2.自变量之间存在多重共线性
#############################################

解决线性回归模型的短板

# 岭回归模型
在线性回归模型的基础之上添加一个l2惩罚项(平方项、正则项)
	'''该模型最终转变成求解圆柱体与椭圆抛物线的焦点问题'''
    
# Lasso回归模型
在线性回归模型的基础之上添加一个l1惩罚项(绝对值项、正则项)
	相较于岭回归降低了模型的复杂度
    '''该模型最终转变成求解正方体与椭圆抛物线的焦点问题'''

交叉验证

将所有数据都参与到模型的构建和测试中 最后生成多个模型
再从多个模型中筛选出得分最高(准确度)的模型

Logistic回归模型

将线性回归模型的公式做Logit变换即为Logistic回归模型
	将预测问题变成了0到1之间的概率问题

混淆矩阵

准确率:表示正确预测的正负例样本数与所有样本数量的⽐值,即(A+D)/(A+B+C+D)。
正例覆盖率:表示正确预测的正例数在实际正例数中的⽐例,即D/(B+D)。
负例覆盖率:表示正确预测的负例数在实际负例数中的⽐例,即A/(A+C)。
正例命中率:表示正确预测的正例数在预测正例数中的⽐例,即D/(C+D),

模型的评估方法

1.ROC曲线
	通过计算AUC阴影部分的面积来判断模型是否合理(通常大于0.8表示OK)
 
2.KS曲线
	通过计算两条折现之间最大距离来衡量模型是否合理(通常大于0.4表示OK)

决策树与随机森林

"""
决策树与随机森林
    默认情况下解决分类问题(买与不买、带与不带、走与不走)
    也可以切换算法解决预测问题(具体数值多少)
"""
树其实是一种计算机底层的数据结构 与现实不同
计算机里面的树都是自上而下的生长

决策树则是算法模型中的一种概念 有三个主要部分
	根节点、枝节点、叶子节点
    	# 根节点与枝节点用于存放条件 叶子节点存放真正的数据结果
        
1.信息熵
	eg:信息熵小相当于红绿灯情况 信息熵大相当于买彩票中奖情况
        
2.条件熵
	条件熵其实就是由信息熵再次细分而来
    	比如有九个用户购买了商品五个没有购买 那么条件熵就是继续从购买不购买的用户中再选择一个条件(比如按照性别计算男和女的熵)
        
3.信息增益
	信息增益可以反映出某个条件是否对最终的分类有决定性的影响
    	在构建决策树时根节点与枝节点所放的条件按照信息增益由大到小排
     
4.信息增益率
	决策树中的ID3算法使⽤信息增益指标实现根节点或中间节点的字段选择,但是该指标存在⼀个⾮常明显的缺点,即信息增益会偏向于取值较多的字段。
    为了克服信息增益指标的缺点,提出了信息增益率的概念,它的思想很简单,就是在信息增益的基础上进⾏相应的惩罚。
    
 
# 基尼指数
	可以让模型解决预测问题
# 基尼指数增益
	与信息增益类似,还需要考虑⾃变量对因变量的影响程度,即因变量的基尼指数下降速度的快慢,下降得越快,⾃变量对因变量的影响就越强

随机森林

随机森林中每颗决策树都不限制节点字段选择,有多棵树组成的随机森林
在解决分类问题的时候采用投票法、解决预测问题的时候采用均值法

K近邻模型

思想:根据位置样本点周边K个邻居样本完成预测或者分类
  
# K值的选择
	 1.先猜测
     2.交叉验证
     3.作图选择最合理的k值
		准确率(越大越好) MSE(越小越好)
        
# 过拟合与欠拟合
    
# 距离
	欧式距离
    	两点之间的直线距离
    曼哈顿距离
    	默认两点直接有障碍物
    余弦相似度
    	论文查重

posted @ 2021-10-24 22:21  wddwyw  阅读(37)  评论(0编辑  收藏  举报