放在前面的话
这学期刻意少选了一些课,希望能够多一些输入,让自己的内在能力提升起来,做一个实干家而不是口嗨家。
于是干脆结合平时数据处理过程中遇到的问题与实战资料,进行系统的总结,形成一篇篇文档。既是对自己学习的记录,也可能对看到的朋友有帮助。由于水平有限目前需要依靠大量的参考资料来支撑,也尽数列在【参考文献】中,可以溯源查看。
非常感谢松鼠在过程中给出的建议和支持,没有松鼠的鼓励可能我完全坚持不到不断完善和更新,有人支持的感觉真好!哈哈哈哈哈
为什么总结Pandas
之前学习Python总觉得各种函数的使用非常“空洞”,不知道针对哪些数据用怎样的方法,像是使用一个一个黑盒,经常发生“报错”。
究其原因,发现是我自己对于数据处理的类型以及对应的方法不够熟悉导致的,因此,在此根据网络资料和kaggle实战总结pandas的相关使用指南。未来数据处理过程中,只要是pandas类型的数据,可以放心使用以下方法达到目的,不会出现报错和意外。
重要的是,本帖子里的方法只是最简单的基础和入门,pandas是一个非常博大精深的库,众多方法和函数具有无限的组合,只是作为初学者的一个初窥。
官方的API地址:API reference — pandas 1.3.3 documentation官方的权威指南,一切问题以官方指南为准。
水平有限肯定有很多不足,如果发现或有任何建议,请朋友一定联系我,感谢!
目录
放在前面的话
为什么总结Pandas
参考文献
特点
用处
导入库
数据类型
Series
DataFrame
Series求交、并、差
Series数据分箱
Series合并为DataFrame
Series转化为特定shape的DataFrame
Series垂直合并
Series字符串数据首字母大写
读写文件
CSV文件
Excel文件
SQL
其它
创建随机矩阵
案例数据
整体操作
数据的行数和列数
查看数据行、列、数据类型、大小
查看数据的基本统计信息:count、mean、std、min、25%、50%、75%、max。
按列操作
查看有哪些列
重命名列名
改变行索引列的名称
每列的数据量
每列去重后的数据量
每列的最大值
每列的最小值
某列的最大值or最小值的索引
每列的均值、中位数、方差、标准差
每列的四分位数
统计每列的所有取值及其出现次数
按某列值排序
每列的求和
累计和、累计积、累计最大值、累计最小值
新列:列计算
列之间的相关系数
按行操作
前n行
后n行
随机抽取n行
返回某列最大的前n行数据
返回某列满足特定值的行
选择与过滤
筛选列
筛选行
筛选特定数据框
筛选器
排序
根据某列的值排序
根据索引排序
删除数据
删除特定的列
删除Series特定值
删除特定的行
数据类型转换
查看数据类型
将某列数据转化为特定的数据类型
Apply函数
def函数
lambda函数
参考文献
-
pandas 在使用时语法感觉很乱,有什么学习的技巧吗? - 知乎
-
pandas 在使用时语法感觉很乱,有什么学习的技巧吗? - 知乎
-
【pandas】 DataFrame 对象的常用计算方法(sum、mean、max、min、idxmax、idxmin、cumsum、mad、std、var、diff、pct_change、corr)_tz_zs的博客-CSDN博客
-
Python的regex模块——更强大的正则表达式引擎 - animalize - 博客园
-
pandas 在使用时语法感觉很乱,有什么学习的技巧吗? - 知乎
-
Python读取Excel存入MySQL_哔哩哔哩_bilibili
-
Python查询MySQL导出到ExcelPython查询MySQL导出到Excel_哔哩哔哩_bilibili
-
使用pandas方法read_html( )6-7 使用pandas方法read_html( )_哔哩哔哩_bilibili
-
pandas.read_html()读取网页表格类数据pandas.read_html()读取网页表格类数据_总裁余(余登武)博客-CSDN博客_pandas read_html
特点
pandas的操作很像搭积木,遇到实际的问题,我们需要不断分解直到最简单的模块组合,再对应具体的pandas函数组合。
用处
pandas是用于数据读写、处理、更改、提取等一系列操作的包,可以说,Excel所有能实现的功能,pandas都可以通过代码轻松实现,因此,pandas对于Python学习非常重要。
导入库
import pandas as pd
数据类型
根据实际场景,Pandas支持两种类型的数据结构。
-
Series
-
Dataframe
Series
Series可以理解成可以“自定义标签”的一维列表,可以人为的设定标签的名称;你可以把它形象的理解成,第一个参数是一个列表(也可以是其它,例如range(0,5)),第二个参数是你希望的列表的索引值。
一般列表默认的索引是从0到n,略显死板;Series可以自定义标签索引,这是它的最大优势
# 自定义一个Series,索引为a,b,c,d
# 注意:Series可以是任意数据类型!比如1和'a'
houSeries = pd.Series([1,2,'a',4], index=['a','b','c','d'])
houSeries
a 1
b 2
c a
d 4
dtype: int64
注意:如果不人为给出索引,那么默认的索引为从0开始
houSeries2 = pd.Series([1,2,3,4])
houSeries2
0 1
1 2
2 3
3 4
dtype: int64
DataFrame
DataFrame可以理解成一个二维的excel表
Series求交、并、差
ser_i = pd.Series(np.intersect1d(ser1, ser2)) # 交集
ser_u = pd.Series(np.union1d(ser1, ser2)) # 并集
ser_s = ser_u[~ser_u.isin(ser_i)]# 差集
Series数据分箱
train['CategoricalFare'] = pd.qcut(train['Fare'], 4)
# 数据分箱,分成4个箱子
目的
连续变量离散化:1~100分成4箱
为什么要分箱?
离散变量便于特征的增加和减少,便于模型快速迭代
稀疏向量内积乘法更快,计算结果便于存储,容易扩展
离散化后的特征对异常数据有很强的鲁棒性,例如,连续异常值5000可能对模型影响很大,但如果分箱后,模型影响很小
为模型引入非线性,提升模型表达能力,加大拟合
模型更加稳定,不会因为各别数据增加而影响模型精度
简化模型,防止模型过拟合
Series合并为DataFrame
# 1.pd.concat()函数
data = pd.concat([ser1, ser2], axis=1)
# 2.pd.DataFrame()函数
data = pd.DataFrame({'col1': ser1, 'col2': ser2})
Series转化为特定shape的DataFrame
# 把series的值提取出来,转化为7x5的矩阵dataframe
data = pd.DataFrame(series.values.reshape(7,5))
Series垂直合并
# 类似列表,直接加在后面
ser3 = ser1.append(ser2)
Series字符串数据首字母大写
# 方法一:title()函数结合lambda
ser.map(lambda x: x.title())
# 方法二upper()结合lambda
ser.map(lambda x: x[0].upper() + x[1:])
# 方法三title()结合列表推导式
pd.Series([i.title() for i in ser])
读写文件
CSV文件
# 读
df = pd.read_csv('data.csv',nrows=5)
# 写
df.to_csv(filename)
Excel文件
# 读
pd.read_excel('filename')
# 写
pd.to_excel('dir/dataFrame.xlsx', sheet_name='Sheet1')
SQL
此处以MySQL为例
首先,我们要创建sqlalchemy对象连接MySQL。
SQLAlchemy的作用,是把关系数据库的表结构映射到对象上,让我们能在Python上间接处理数据。
pip install sqlalchemy pip install mysql-connector-python
# 导入库
from sqlalchemy import create_engine
# 连接MySQL数据库
engine = create_engine("mysql+mysqlconnector://root:123456@127.0.0.1:3306/test",echo=False)
# 参数含义:mysql表示使用MySQL数据库;mysqlconnector表示使用库;root是用户名;“:”后、“@”前是我们的密码;@后是host地址;端口号是3306;最后是数据库的名字“test”
# echo=False表示不输出sql语句
其次,我们从sql中读取数据。
import pymysql
conn = pymysql.connect(
host = '127.0.0.1', #数据库的host
user='root', #用户名
passwd='12345678', #密码
port=3306, #port
db='db_school' #数据库的名字
charset='utf8' #处理中文数据
)
df = pd.read_sql("""
select * from student_grade
""", con=conn)
随后,我们把Python数据写入sql中。
# 方法1当数据表不存在时,每次覆盖整个表
df.to_sql(name='student', con=engine, if_exists="replace")
# name为sql表名;con为连接,对应engine;if_exists=“replace”表示覆盖。
# 方法2当数据表已经存在时,追加即可
df.to_sql(name='student', con=engine, if_exists="append")
其它
# 分隔符文本的读
pd.read_table(filename)
# json格式的读写
pd.read_json(json_string)
df.to_json(filename)
# 传入html格式,进行解析
# 注意:read_html只能读取网页中的表格类数据!
# 注意:一般只能处理静态网页;动态网页要用selenium
pd.read_html(url)
df.to_html(filename)
# 剪切板
pd.read_clipboard()
df.to_clipboard()
创建随机矩阵
# 创建一个10行5列的随机数矩阵
pd.DataFrame(np.random.rand(10,5))
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | 0.671785 | 0.879404 | 0.350473 | 0.689689 | 0.857887 |
1 | 0.710817 | 0.495626 | 0.361229 | 0.683298 | 0.872921 |
2 | 0.623185 | 0.245117 | 0.281589 | 0.531199 | 0.893249 |
3 | 0.373295 | 0.432649 | 0.842731 | 0.127529 | 0.713869 |
4 | 0.038610 | 0.641308 | 0.903039 | 0.829121 | 0.395986 |
5 | 0.774026 | 0.856268 | 0.184218 | 0.058289 | 0.145508 |
6 | 0.758030 | 0.495285 | 0.867913 | 0.411790 | 0.781194 |
7 | 0.245190 | 0.618623 | 0.738077 | 0.300838 | 0.992442 |
8 | 0.492621 | 0.723553 | 0.958007 | 0.834120 | 0.618777 |
9 | 0.944307 | 0.877147 | 0.175041 | 0.058599 | 0.470091 |
案例数据
后文代码中使用的数据为2021东京奥运会各国的奖牌数量统计,包括:加权排名、国家、金牌数量、银牌数量、铜牌数量、金牌总计、奖牌数量排名
整体操作
数据的行数和列数
拿到数据第一步往往先查看数据有多少行、多少列。
如果在Excel里,需要翻到最低和最右,而且可能由于溢出无法穷尽;Python可以简单的实现。
data.shape
查看数据行、列、数据类型、大小
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 93 entries, 0 to 92
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Rank 93 non-null int64
1 Team/NOC 93 non-null object
2 Gold 93 non-null int64
3 Silver 93 non-null int64
4 Bronze 93 non-null int64
5 Total 93 non-null int64
6 Rank by Total 93 non-null int64
dtypes: int64(6), object(1)
memory usage: 5.2+ KB
数据的行数、索引、列、每列的非缺失值数量、数据类型、数据的内存大小
查看数据的基本统计信息:count、mean、std、min、25%、50%、75%、max。
data.describe()
按列操作
这里的操作可以想象是Excel中,对每列数据进行统计和观察。
查看有哪些列
拿到数据后,我们先看一下数据有哪些列
# 注意,不用加()因为没有要传入的参数
data.columns
Index(['Rank', 'Team/NOC', 'Gold', 'Silver', 'Bronze', 'Total',
'Rank by Total'],
dtype='object')
重命名列名
当我们发现一些列名比较奇怪或者不规范需要更改的时候,Excel里我们需要“找到需要更改的列名——点击表格——编辑”,pandas我们可以用代码更改。
# 把“Gold”名字改成“金牌”
# columns中,第一个参数为原名,:后为新名
data.rename(columns= {'Gold' : '金牌'}).head()
Rank | Team/NOC | 金牌 | Silver | Bronze | Total | Rank by Total | |
---|---|---|---|---|---|---|---|
0 | 1 | United States of America | 39 | 41 | 33 | 113 | 1 |
1 | 2 | People's Republic of China | 38 | 32 | 18 | 88 | 2 |
2 | 3 | Japan | 27 | 14 | 17 | 58 | 5 |
3 | 4 | Great Britain | 22 | 21 | 22 | 65 | 4 |
4 | 5 | ROC | 20 | 28 | 23 | 71 | 3 |
改变行索引列的名称
data.index.name = 'ye'
ye | |||||||
---|---|---|---|---|---|---|---|
0 | 1 | United States of America | 39 | 41 | 33 | 113 | 1 |
1 | 2 | People's Republic of China | 38 | 32 | 18 | 88 | 2 |
2 | 3 | Japan | 27 | 14 | 17 | 58 | 5 |
3 | 4 | Great Britain | 22 | 21 | 22 |
每列的数据量
我希望统计每列数据有多少行,如果在Excel里,我们可能需要翻到最后一页。Python只需要一行代码。
data.count()
# 或 len(data)
Rank 93
Team/NOC 93
Gold 93
Silver 93
Bronze 93
Total 93
Rank by Total 93
dtype: int64
表示Rank列有93行数据
每列去重后的数据量
有时候我们希望看到每列有多少独特的值,特别是当独特值具有关键意义的时候。
# 注意是nunique()而不是unique()!!
data.nunique()
Rank 67
Team/NOC 93
Gold 14
Silver 17
Bronze 21
Total 30
Rank by Total 30
dtype: int64
每列的最大值
我们希望看到每一列的最大值,例如,我们希望知道“获得金牌最多的”有多少?
# 统计每列数据的最大值:例如,我想看得到金牌、银牌、铜牌数量最多为多少?
data.max()
Rank 86
Team/NOC Venezuela
Gold 39
Silver 41
Bronze 33
Total 113
Rank by Total 77
dtype: object
每列的最小值
同理,我们想知道,获得金牌最少的是多少?
# 统计每列的最小值:例如,我想看金牌最低的为多少?
data.min()
Rank 1
Team/NOC Argentina
Gold 0
Silver 0
Bronze 0
Total 1
Rank by Total 1
dtype: object
某列的最大值or最小值的索引
有时候我们不仅需要直到最大值或最小值是谁,我们也希望直到对应的索引是多少,便于我们定位。
由于要定位索引,必须要针对某列,不能针对Dataframe整体,必须筛选列;Series可以直接用。
# 'Gold'列的最小值的索引
data['Gold'].idxmin()
# 'Gold'列的最大值的索引
data['Gold'].idxmax()
每列的均值、中位数、方差、标准差
除了最基本的量、最大最小值,我们还希望了解每列数据的一些基本的统计特征。例如,平均金牌数量?金牌数量的中位数?队伍之间获得金牌的数量的差异大吗(方差or标准差)
# 均值
data.mean()
Rank 46.333333
Gold 3.655914
Silver 3.634409
Bronze 4.322581
Total 11.612903
Rank by Total 43.494624
dtype: float64
有趣的是,pandas会自动把非数字的列给忽视掉,只计算数值列的均值
# 中位数
data.median()
Rank 46.0
Gold 1.0
Silver 1.0
Bronze 2.0
Total 4.0
Rank by Total 47.0
dtype: float64
# 标准差
data.std()
Rank 26.219116
Gold 7.022471
Silver 6.626339
Bronze 6.210372
Total 19.091332
Rank by Total 24.171769
dtype: float64
# 方差
data.var()
Rank 687.442029
Gold 49.315101
Silver 43.908368
Bronze 38.568724
Total 364.478962
Rank by Total 584.274427
dtype: float64
每列的四分位数
除了总的均值、方差这些量,我们有时候希望获得数据的阶段性情况,例如,我想知道“前25%的人的金牌数量大约为多少”(从小到大),第75%的人的金牌数量大约为多少。
这时,我们需要引入四分位数。
具体取25%还是75%,取几个点,可以根据自己的喜好设定。
data.quantile([0.25, 0.5, 0.75])
Rank | Gold | Silver | Bronze | Total | Rank by Total | |
---|---|---|---|---|---|---|
0.25 | 24.0 | 0.0 | 0.0 | 1.0 | 2.0 | 23.0 |
0.50 | 46.0 | 1.0 | 1.0 | 2.0 | 4.0 | 47.0 |
0.75 | 70.0 | 3.0 | 4.0 | 5.0 | 11.0 | 66.0 |
每一列数据,从小到大排序,第25%、第50%、第75%的数据为多少。
结果发现,由于50%时的金牌为1,说明至少有大约50%的国家,没有金牌或只有1枚金牌。
统计每列的所有取值及其出现次数
例如,我想要知道,金牌的数量一共有哪些?获得39块金牌的共有多少人?获得0块金牌的共有多少人?
对应在Excel的操作是:“数据——自动筛选——统计值的出现次数”
# 统计Gold列的值的出现次数
data['Gold'].value_counts()
0 28
1 22
2 11
3 11
4 5
7 4
10 4
6 2
17 1
20 1
22 1
27 1
38 1
39 1
Name: Gold, dtype: int64
第一列为值,第二列为出现频次。
结果说明,共有28个国家一枚金牌都没有获得,有一个国家获得了39枚金牌。
按某列值排序
例如,我们希望数据根据“金牌列”进行升序排序;对应Excel里面的排序操作。
# 默认为升序
# 添加参数ascending= False则变成降序
data.sort_values('Gold').head()
Rank | Team/NOC | Gold | Silver | Bronze | Total | Rank by Total | |
---|---|---|---|---|---|---|---|
92 | 86 | Syrian Arab Republic | 0 | 0 | 1 | 1 | 77 |
65 | 66 | Colombia | 0 | 4 | 1 | 5 | 42 |
66 | 67 | Azerbaijan | 0 | 3 | 4 | 7 | 33 |
67 | 68 | Dominican Republic | 0 | 3 | 2 | 5 | 42 |
68 | 69 | Armenia | 0 | 2 | 2 | 4 | 47 |
每列的求和
求每列的值的总和,例如,整个2021东京奥运会,一共有多少枚金牌?
data.sum()
Rank 4309
Team/NOC United States of AmericaPeople's Republic of C...
Gold 340
Silver 338
Bronze 402
Total 1080
Rank by Total 4045
dtype: object
累计和、累计积、累计最大值、累计最小值
有时候我们希望列之间实现累加叠积的关系,例如,随着国家的增多,累计金牌数量的变化?
# 累计求和:依次统计前1、2、3、4、5...n行的累计和
data.cumsum()
Rank | Team/NOC | Gold | Silver | Bronze | Total | Rank by Total | |
---|---|---|---|---|---|---|---|
0 | 1 | United States of America | 39 | 41 | 33 | 113 | 1 |
1 | 3 | United States of AmericaPeople's Republic of C... | 77 | 73 | 51 | 201 | 3 |
2 | 6 | United States of AmericaPeople's Republic of C... | 104 | 87 | 68 | 259 | 8 |
3 | 10 | United States of AmericaPeople's Republic of C... | 126 | 108 | 90 | 324 | 12 |
4 | 15 | United States of AmericaPeople's Republic of C... | 146 | 136 | 113 | 395 | 15 |
... | ... | ... | ... | ... | ... | ... | ... |
88 | 3965 | United States of AmericaPeople's Republic of C... | 340 | 338 | 398 | 1076 | 3737 |
89 | 4051 | United States of AmericaPeople's Republic of C... | 340 | 338 | 399 | 1077 | 3814 |
90 | 4137 | United States of AmericaPeople's Republic of C... | 340 | 338 | 400 | 1078 | 3891 |
91 | 4223 | United States of AmericaPeople's Republic of C... | 340 | 338 | 401 | 1079 | 3968 |
92 | 4309 | United States of AmericaPeople's Republic of C... | 340 | 338 | 402 | 1080 | 4045 |
# 累计积:切忌不能放入字符串进去,必须为可计算的数值
data.cumprod()
# 累计最大值
data.cummax()
# 累计最小值
data.cummin()
新列:列计算
有时候我们需要对多列之间进行计算,得到第三列作为我们所需要的列。
例如,我们希望统计每个国家的金牌和银牌的数量,我们把两列想加得到第三列
data["gold_Silver"] = df.Gold + df.Silver
列之间的相关系数
data.corr()
按行操作
前n行
当数据量比较大的时候,我们会查看前n行大致了解一下
# .head()默认前5行,可以根据参数改变
data.head()
后n行
# 同head
data.tail()
随机抽取n行
# 默认抽取一行
data.sample()
返回某列最大的前n行数据
比如我想知道,银牌数量最多的前n个数据的样子是怎样的
data.nlargest(5,'Gold')
返回某列满足特定值的行
例如,我想知道,银牌数量大于10的国家都有哪些
data[data.Silver>10]
选择与过滤
筛选列
选择特定的列
# 选择'Gold'列的数据
data['Gold']
# 同理
data.Gold
# 根据列名筛选:筛选Gold和Silver列
data[['Gold','Silver']]
筛选行
选择特定的行
# 筛选第10行到最后的数据
data[10:]
# 返回索引从5~7的行数据
data.loc[5:7]
# 筛选某列数据的某一行
data['Gold'][0]
筛选特定数据框
-
筛选第n行第m列的数据框
-
筛选第~行第~列的数据框
# 返回第2行,第3列的数据框
data.iloc[[1],[2]]
# 根据行索引和列名筛选
data.loc[:,"Gold":"Bronze"]
筛选器
# 自己创建过滤条件
filters = data.Gold>5
data[filters]
# 使用.filter函数和regex匹配
# regex='^G'表示匹配开头为G的列
data.filter(regex='^G').head()
# 多重条件
# (1)np.logical_and()函数
data[np.logical_and(data['Gold']>10,data['Silver']<50)]
# (2)直接使用&
data[(data['Gold']>10)&(data['Silver']<50)]
Python内置的正则表达式引擎——regex模块
常见的正则模块re有4270行C语言代码,而regex模块有24513行C语言代码,更加强大!!
排序
根据某列的值排序
data.sort_values('Gold',ascending=False).head()
根据索引排序
# 默认升序
data.sort_index()
删除数据
删除特定的列
# columns=不能省!!
data.drop(columns=['Gold'])
data.drop(columns=['Gold','Silver'])
# 使用axis参数:删除Gold列
data.drop('Gold', axis=1)
删除Series特定值
# 删除Series中索引为'a'值
hou_Series.drop('a')
删除特定的行
# 删除索引为0,1的行
data.drop([0,1])
数据类型转换
查看数据类型
查看每列数据是整型?浮点?字符串?
data.dtypes
将某列数据转化为特定的数据类型
# dataType为特定的数据类型
data['Gold'] = data['Gold'].astype('dataType')
Apply函数
有时候我们需要自定义实现一些个性化的功能,这时我们可以通过apply函数实现
def函数
def power(x):
return x*2
data.Gold.apply(power).head()
lambda函数
df.Gold.apply(lambda x: x*2).head()