前言
开刷Pandas数据分析,看起来很好理解,不过没做笔记没敲代码心里总是不安稳,所以复现下课程代码并演示其中遇到的问题,顺便水一水笔记好了
参考资料:
课程视频链接:Pandas数据分析从入门到实战
数据及代码示例:ant-learn-pandas: pandas学习课程代码仓库 (gitee.com)
一、数据读取
- 数据类型
 
| 数据类型 | 说明 | Pandas读取方法 | 
|---|---|---|
| csv, tsv, txt | 用逗号、tab或其它字符分割的文本文件 | read_csv | 
| excel | xls或xlsx文件 | read_excel | 
| mysql | 关系型数据表 | read_sql | 
- read_csv
 
1.1 读取csv文件
csv是以逗号分割的文本文件,如下:
1  | csv复制代码userId,movieId,rating,timestamp  | 
直接使用read_csv读取该文件
1  | py复制代码fpath = "../datas/ml-latest-small/ratings.csv"  | 
1.2 指定分割符
已知access_pvuv.txt如下:
1  | txt复制代码2019-09-10 139 92  | 
为read_csv添加参数delimiter (或seq) 指定分隔符,header=None表示没有第一行列名称
1  | py复制代码fpath = "../datas/crazyant/access_pvuv.txt"  | 
- read_excel
 
1  | py复制代码fpath = "../datas/crazyant/access_pvuv.xlsx"  | 
- read_sql
 
3.1 使用pymysql
连接数据库,选择编码方式
1  | py复制代码import pandas as pd  | 
1  | py复制代码table = pd.read_sql("select * from tbname", con=conn)  | 
但是会报警告:
UserWarning: pandas only supports SQLAlchemy connectable (engine/connection) or database string URI or sqlite3 DBAPI2 connection. Other DBAPI2 objects are not tested. Please consider using SQLAlchemy.
这里建议我们使用SQLAlchemy
3.2 使用SQLAlchemy
1  | py复制代码import pandas as pd  | 
- 查看数据格式
 
1  | py复制代码# 查看前几行数据,默认为5行  | 
二、数据结构
- Series
 
1  | py复制代码import pandas as pd  | 
1  | py复制代码# 指定索引创建Series  | 
1  | py复制代码# 字典创建Series  | 
- DataFrame
 
1  | py复制代码import pandas as pd  | 
1  | py复制代码# 输出DataFrame的索引、列标签以及数据类型  | 
三、查询数据
- 查询方法
 
- df.loc :基于标签索引,结果包含最后一个标签的值
 - df.iloc:基于位置索引,结果不包含最后一个位置的值
 - df.where
 - df.query
 
本节主要介绍df.loc
- 数据预处理
 
1  | py复制代码import pandas as pd  | 
1  | py复制代码# 设定索引为日期,方便按日期筛选  | 
1  | py复制代码# 替换掉温度的后缀℃  | 
1  | py复制代码print(df.head())  | 
这里会报一个警告:
1  | cmd复制代码 DeprecationWarning: In a future version, `df.iloc[:, i] = newvals` will attempt to set the  | 
- 按数值、列表、区间查询
 
1  | py复制代码# 得到单个值  | 
1  | py复制代码# 得到一列/一行  | 
1  | py复制代码# 得到DataFrame  | 
1  | py复制代码# 按区间查询  | 
- 条件查询
 
1  | py复制代码# 查询最高温度小于30度,并且最低温度大于15度,并且是晴天,并且天气为优的数据  | 
其中,条件表达式返回的是一个布尔值的Series
1  | py复制代码# 观察条件表达式  | 
- 函数查询
 
1  | py复制代码# 直接写lambda表达式  | 
1  | py复制代码# 编写自己的函数,查询9月份,空气质量好的数据  | 
四、新增数据列
- 直接赋值
 
1  | py复制代码df.loc[:, 'wencha'] = df['bWendu'] - df['yWendu']  | 
- df.apply
 
传入一个函数并选定axis:
- 当axis=1,函数的参数为一行的Series(常用)
 - 当axis=0,函数的参数为一列的Series
 
1  | py复制代码def get_wendu_type(x):  | 
- df.assign
 
df.assign总是会创建一个新的copy
利用lambda表达式,处理原来的数据得到新列
1  | ini复制代码# 可以同时添加多个新的列  | 
- 条件选择分组后赋值
 
1  | py复制代码# 先创建空列(这是第一种创建新列的方法)  | 
错误示例:
1  | py复制代码df.loc[df["bWendu"]-df["yWendu"]>10]["wencha_type"] = "温差大"  | 
两个[]的链式操作相当于
1  | py复制代码df.get(condition).set(wen_cha)  | 
这里get得到的结果可能是view也可能是copy,存在歧义
正确示范:
1  | py复制代码df.loc[df["bWendu"]-df["yWendu"]>10, "wencha_type"] = "温差大"  | 
五、聚合查询
- describe输出统计结果
 
1  | py复制代码# 一下子提取所有数字列统计结果  | 
1  | cmd复制代码 bWendu yWendu aqi aqiLevel wencha  | 
describe只能得到数值列的统计结果
- 非数值列统计
 
2.1 unique唯一去重
1  | py复制代码print(df['tianqi'].unique())  | 
1  | cmd复制代码['晴~多云' '阴~多云' '多云' '阴' '多云~晴' '多云~阴' '晴' '阴~小雪' '小雪~多云' '小雨~ 阴' '小雨~雨夹雪'  | 
2.2 value_counts按值计数
1  | py复制代码print(df['wencha_type'].value_counts())  | 
1  | cmd复制代码温差正常 187  | 
- 协方差和相关系数
 
1  | py复制代码print(df.cov(), '\n\n', df.corr())  | 
1  | cmd复制代码 bWendu yWendu aqi aqiLevel wencha  | 
六、缺失值处理
- 处理方式
 
Pandas使用这些函数处理缺失值:
- isnull和notnull:检测是否是空值,可用于df和series
 - dropna:丢弃、删除缺失值
- axis : 删除行还是列,{0 or ‘index’, 1 or ‘columns’}, default 0
 - how : 如果等于any则任何值为空都删除,如果等于all则所有值都为空才删除
 - inplace : 如果为True则修改当前df,否则返回新的df
 
 - fillna:填充空值
- value:用于填充的值,可以是单个值,或者字典(key是列名,value是值)
 - method : 等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill
 - axis : 按行还是列填充,{0 or ‘index’, 1 or ‘columns’}
 - inplace : 如果为True则修改当前df,否则返回新的df
 
 
- 数据清洗示例
 
2.1 检测空值
1  | py复制代码# 跳过前面两空行  | 
1  | cmd复制代码 Unnamed: 0 姓名 科目 分数  | 
2.2 dropna示例
1  | py复制代码# 删除全为空的行和列  | 
1  | cmd复制代码 姓名 科目 分数  | 
2.3 fillna示例
1  | py复制代码# 将空的分数填充为0  | 
1  | cmd复制代码 姓名 科目 分数  | 
七、数据排序
- 排序方法
 
- Series的排序:
 
Series.sort_values(ascending=True, inplace=False)
参数说明:
- ascending:默认为True升序排序,为False降序排序
 - inplace:是否修改原始Series
 
- DataFrame的排序:
 
DataFrame.sort_values(by, ascending=True, inplace=False)
参数说明:
- by:字符串或者List<字符串>,单列排序或者多列排序
 - ascending:bool或者bool的列表,升序还是降序,如果是list对应by的多列
 - inplace:是否修改原始DataFrame
 
- 排序示例
 
1  | py复制代码# Series的排序  | 
1  | cmd复制代码ymd  | 
1  | py复制代码# DataFrame的排序  | 
1  | cmd复制代码 aqi bWendu  | 
八、字符串处理
- Pandas的str
 
Pandas的字符串处理:
- 使用方法:先获取Series的str属性,然后在属性上调用函数;
 - 只能在字符串列上使用,不能数字列上使用;
 - Dataframe上没有str属性和处理方法
 - Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似;
 
- 基础用法
 
获取str属性,并调用各种方法,如replace, isnumeric, len
1  | py复制代码print(df['wencha_type'].str.len())  | 
1  | cmd复制代码ymd  | 
- 条件查询
 
或使用contains, startswith等得到bool的Series做条件查询
1  | py复制代码print(df.loc[df['tianqi'].str.startswith('多云'), ['tianqi', 'fengxiang']])  | 
1  | cmd复制代码 tianqi fengxiang  | 
- 正则表达式
 
由于Series.str天然支持正则表达式,示例如下:
匹配字符集合并做替换:
1  | py复制代码# 添加新列  | 
1  | cmd复制代码86 20180328  | 
捕获组提取数据:
1  | py复制代码extracted_fengli = df['fengli'].str.extract(r'(\d)-(\d)')  | 
1  | cmd复制代码 0 1  | 
九、索引
- 索引的作用
 
选择恰当的索引可以加速查询性能
- 当索引是唯一的时,Pandas会用哈希表优化性能,时间复杂度为O(1)
 - 当索引不唯一,但是单调时,Pandas会使用二分查找,时间复杂度为O(log n)
 - 当索引既不唯一且不单调时,Pandas只能遍历,时间复杂度为O(n)
 
因此,我们要判断当前索引是否为以上类型,尽可能选择唯一的索引,单调次之
- 选择索引示例
 
原始数据如下:
1  | py复制代码print(df.head())  | 
1  | cmd复制代码 userId movieId rating timestamp  | 
判断每一列是否存在唯一约束:
1  | py复制代码print(df.nunique() == len(df))  | 
1  | cmd复制代码userId False  | 
判断每一列是否单调:
1  | py复制代码  | 
1  | cmd复制代码userId True  | 
- 设置索引示例
 
DataFrame.set_index(keys, append=False, drop=True, inplace=False)
keys代表被用作索引的列
append代表是否保留原来的索引
drop表示是否将指定的列在原数据列中删除
inplace表示是否在原数据上修改
1  | py复制代码df.set_index('userId',append=True, drop=False, inplace=True)  | 
1  | cmd复制代码 userId movieId rating timestamp  | 
本文转载自: 掘金