Pandas技巧大全:含具体代码实现
Posted Wan7777777
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pandas技巧大全:含具体代码实现相关的知识,希望对你有一定的参考价值。
放在前面的话
这学期刻意少选了一些课,希望能够多一些输入,让自己的内在能力提升起来,做一个实干家而不是口嗨家。
于是干脆结合平时数据处理过程中遇到的问题与实战资料,进行系统的总结,形成一篇篇文档。既是对自己学习的记录,也可能对看到的朋友有帮助。由于水平有限目前需要依靠大量的参考资料来支撑,也尽数列在【参考文献】中,可以溯源查看。
非常感谢松鼠在过程中给出的建议和支持,没有松鼠的鼓励可能我完全坚持不到不断完善和更新,有人支持的感觉真好!哈哈哈哈哈
为什么总结Pandas
之前学习Python总觉得各种函数的使用非常“空洞”,不知道针对哪些数据用怎样的方法,像是使用一个一个黑盒,经常发生“报错”。
究其原因,发现是我自己对于数据处理的类型以及对应的方法不够熟悉导致的,因此,在此根据网络资料和kaggle实战总结pandas的相关使用指南。未来数据处理过程中,只要是pandas类型的数据,可以放心使用以下方法达到目的,不会出现报错和意外。
重要的是,本帖子里的方法只是最简单的基础和入门,pandas是一个非常博大精深的库,众多方法和函数具有无限的组合,只是作为初学者的一个初窥。
官方的API地址:API reference — pandas 1.3.3 documentation官方的权威指南,一切问题以官方指南为准。
水平有限肯定有很多不足,如果发现或有任何建议,请朋友一定联系我,感谢!
目录
查看数据的基本统计信息:count、mean、std、min、25%、50%、75%、max。
参考文献
-
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()
以上是关于Pandas技巧大全:含具体代码实现的主要内容,如果未能解决你的问题,请参考以下文章