前言
开刷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 |
本文转载自: 掘金