10/18
今日考题
1.谈谈缺失数据的概念以及处理缺失数据的方法有哪些
丢失数据出现在重新创建索引或者是两个Series进行运算的情况下
有索引没有固定的数据则会出现 NaN 即数据缺失
NaN是一个浮点型数据 不太常用的方法可以直接dropna去删除这一数据
或者是通过fillna() 或者在运算中通过fill_value() 去直接填充所需要的值
2.pandas两大数据结构是什么,各自有何特征,如何创建
Series 和 DataFrame
# Series
pd.Series([1,2,3],index=['a','b','c'])
pd.Series({"a":1,"b":2})
它可以视作一个带索引的一维数组(数组概念建议移步numpy模块)
# DataFrame
pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3],index=['b','a','c'])})
它可以看成是多个Series的组合 同时携带表头
3.pandas如何读取外部数据
pd.read_csv() # 读取文本文件和.csv(苹果的表格文件)文件数据
pd.read_html() # 读页面上table标签内所有的数据 不是table标签读不了
pd.read_excel() # 读excel表格文件数据
pd.read_sql() # 读MySQL表格数据
'''每个方法都有自己规定的参数
从上至下参数逐渐减少变的简单'''
4.数据概览常用方法有哪些
mlb.columns # 查看表头
mlb.index # 查看一行行索引
mlb.shape # 行列
mlb.dtypes # 数据类型
mlb.head() # 从头取多条数据
mlb.tail() # 从末尾取多条数据
复习巩固
- DataFrame基本介绍
# DF是一种表格型数据结构
# 自定义创建DataFrame的方式
import pandas as pd
pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})
- 读取外部数据四种方式
"""
1.方法名后面加问号运行查看
2.方法名后面按住shift+tab
"""
1.read_csv() # 读取文本文件、csv文件数据
filepath_or_buffer:文件路径
sep:分隔符
headers:判断是否含有表头
names:自定义列字段名词
encoding:自定义字符编码
converters:数据类型的转换
...
2.read_excel() # 读取xlsx等excel表格文件
3.read_html() # 读取HTML页面上table标签内的数据
4.read_sql() # 读取数据库里面的表格数据(MySQL)
pymysql模块
conn = pymysql.connect(
host,port,user,passwd,db,charset
)
- 数据概览
.index # 查看行标签
.columns # 查看列字段
.dtyeps # 查看数据类型
.shape # 查看行列数
.head # 查看前面几条数据
.tail # 查看末尾几条数据
.describe # 快速统计
- 数据操作
# 读取列数据
df['列名称'] # df.列名称 改方法有时候会出现关键字冲突的情况
# 如何读取多列
df[['列名称1','列名称2','列名称']]
# 如何创建新的列
df['新列名称'] = 新的列数据 # 既可以是自己指定也可以来自于其他列数据
# 按照指定的条件筛选数据
df.loc[df['Brand'] == '众泰']
df.loc[(df['Brand'] == '众泰') | (df['New_price'] > 10)]
df.loc[df['Brand'] == '众泰',['Brand','Names','New_price']]
内容概要
主体:pandas模块结束,matplotlib模块
- pandas其他操作补充
- pandas实战案例
- 可视化模块matplotlib
详细讲解
缺失值识别和处理
# 遇上缺失值首先想一下那四个有关NaN的方法
1. isnull # 是NaN为True
2. notnull # 不是NaN为True
3. dropna # 丢弃缺失值
4. fillna # 填充数据
'''简单的四个方法涵盖了数据处理缺失值问题的所有办法了'''
data05 = pd.read_excel(r'data_test05.xlsx')
data05.head() # 首先导入数据 然后拿前面几行看一下
data05.isnull().any(axis = 0) # 简单的isnull后面加上any参数 就能查看到列字段下哪些有丢失
data05.isnull().sum(axis = 0) # 同时还有更好用的sum可以看到缺失几个数据
data05.isnull().sum()/data05.shape[0] # 拿每列缺失的数据数量除以总行数就知道占比
'''如果数据缺失占比非常小 比如小于1可以考虑直接删除'''
然后就来到缺失处理的关键部分了
这里自然不能用0填充的 字母操作往下看
##############################################################
data05.fillna(value = {
'gender':data05.gender.mode()[0], # mode众数哪个多用哪个
'age':data05.age.mean(), # meam平均值 年龄不会受极端值影响
'income':data05.income.median() # 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')
然后把颜色作为行标签 每个颜色的平均价格作为数据构建透视表
pd.pivot_table(data06,
index = 'color',
values='price',
aggfunc='mean' # 聚合的关键字aggregate加功能function
)
分组与聚合
分组非常简单 通过关键字group去控制
# ep:通过color和cut分组 就是先用color分 分完之后color中再通过cut细分
data06.groupby(by = ['color','cut']) # 由于分组之后只能拿到分组依据这边甚至直接优化不给你看了
想要看到的话就要指定额外的参数
# 先将刚才分好组的数据赋值给一个变量
d6g = data06.groupby(by = ['color','cut'])
# 然后通过关键字aggregate 然后再通过numpy的功能筛选出一个个数组中的聚合结果
d6g.aggregate({'color':np.size,'price':np.mean,'table':np.max})
之后也可以调整表头的数据顺序
result = pd.DataFrame(result, columns=['color','carat','price','table']) # 想要什么顺序就按照什么顺序写入列表
也可以对变换之后的表做重命名
res.rename(columns={'color':'counts',
'price':'avg_price',
'table':'max_table'})
# 在字典后面加上,inplace = True就能确认修改了
小练习
# 分析NBA各球队冠军次数和球员FMVP次数
champion = pd.read_html('https://baike.baidu.com/item/NBA%E6%80%BB%E5%86%A0%E5%86%9B/2173192?fr=aladdin')[0] # 通过索引0取到所需的表
然后先做一些简单的处理让表变得合规一些也方便处理
# 先将表头部分替换成表的索引0那行
champion.columns = champion.iloc[0]
# 然后将索引0那行去掉
champion.drop(index = 0 , inplace = True)
做好前期准备之后就可以来进行后续的处理了
# 通过aggregate可以获取分组之后的数据展示
champion.groupby(by='冠军').aggregate({'冠军':np.size}) # size计算数组大小这里就可以看作是count
# 这样就拿到了各个队伍的总冠军数
# 也可以这样进行夺冠计数
champion.groupby('冠军').size() # 这里size是获取整个表单变成Series了
随后对Series进行排序就简单了
champion.groupby('冠军').size().sort_values(ascending=False)
# 在后面加上.sort_values(ascending=False) 降序排列
# 如果要查看队伍冠军和MVP数量可以把两者直接扔进groupby里面然后size转换
champion.groupby(['冠军', 'FMVP']).size()
也可以通过dataFrame直接改就是会麻烦点
cp = champion.groupby(by='冠军').aggregate({'冠军':np.size})
# 首先把上面得到的DF数据赋值给到变量方便后续操作
# 由于排序一定需要by参数 即通过其中一项数据排序所以要将表头的冠军替换
不然就会出现冲突
# 但是这里很怪重命名的时候又不会选择到前面那个字符
cp.rename(columns={"冠军":"num"},inplace = True)
# 应该是把这个视作行标签的表头 h或者说看作是Series的行标签
之后再通过by来排序就行了
cp.sort_values(by="num",ascending=False)
数据合并
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:为合并后的数据添加新索引,用于区分各个数据部分
# 这个和SQL里面的联表很像 横向合并基本一摸一样
# 数据准备
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参数可以在合并之后看到数据来源 其实并没有啥大用处不加也行
对于刚才那个没什么用的key还有对应的方法.reset_index()
可以重新创建一个和key对应的行标签
这里可以看到level_1里面的行标签还是有些问题的需要调整
或者可以直接去掉
pd.concat([df1,df2]).reset_index().drop(columns='index')
最后配合上前面可以用key创建索引可以整合成
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.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:如果数据连接的结果中存在重叠的变量名,则使用各自的前缀进行区分
'''程序员都要使用Github所以对merge不会陌生
就是合并 这个合并再Github里面就是合并代码'''
# 首先还是先构造数据集
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]})
然后看一下联表操作是不是真就和SQL里面一摸一样
# 连接df3和df4
mix = pd.merge(left = df3, # 规定左表
right = df4, # 规定右表
how = 'inner', # 连接方式
left_on='id', # 左表中连接关键字id注意这里是df3自生的id
right_on='Id') # 右表中连接关键字Id
之后再将连好的结果和df5连接
pd.merge(left = mix,
right = df5,
how = 'left') # 这里有完全对应的字段就不需要再去指定on
matplotlib简介
是一个强大的python绘图和数据可视化工具包,数据可视化也是我们数据分析重要环节之一,可以帮助我们分析出很多价值信息,也是数据分析的最后一个可视化阶段
# python纯开发环境下
pip3 install matplotlib
# anaconda环境下
conda install matplotlib
'''anaconda已经自动帮助我们下载好了数据分析相关的模块,其实无需我们再下载'''
import matplotlib.pyplot as plt
饼图
饼图属于最传统的统计图形之一,几乎随处可见,例如大型公司的屏幕墙、各种年度论坛的演示稿以及各大媒体发布的数据统计报告等;
饼图是将一个圆分割成不同大小的楔(扇)形,而圆中的每一个楔形代表了不同的类别值,通常根据楔形的面积大小来判断类别值的差异;
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] # 比例
edu_lv = ['中专','大专','本科','硕士','其他'] # 对应的学历
exp = [0,0.1,0,0,0.5] # 炸开的距离
# 防止图像出错 如果python版本比较低图像可能是扁平的
# plt.axes(aspect='equal') # 加上这个代码就可以了
'''全部准备好就可以开绘制图形了'''
plt.pie(x = edu, # 绘图数据
labels=edu_lv, # 添加教育水平标签
autopct='%.1f%%', # 设置百分比的格式,这里保留一位小数
explode = exp
)
%matplotlib() # 这个东西能让窗口独立展示 跑一遍之后删了这行再跑一遍
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')
'''这部分可能不太好理解前面循环取值
GDP['GDP']这是个带索引的Seriies
那x就是索引 y就是GDP合起来就变成了图上的坐标
然后round是python自带的四舍五入方法
ha是文字形式 居中'''
# 显示图形
plt.show()