Pandas技巧大全:含具体代码实现

放在前面的话                

        这学期刻意少选了一些课,希望能够多一些输入,让自己的内在能力提升起来,做一个实干家而不是口嗨家。

        于是干脆结合平时数据处理过程中遇到的问题与实战资料,进行系统的总结,形成一篇篇文档。既是对自己学习的记录,也可能对看到的朋友有帮助。由于水平有限目前需要依靠大量的参考资料来支撑,也尽数列在【参考文献】中,可以溯源查看。

        非常感谢松鼠在过程中给出的建议和支持,没有松鼠的鼓励可能我完全坚持不到不断完善和更新,有人支持的感觉真好!哈哈哈哈哈

为什么总结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是用于数据读写、处理、更改、提取等一系列操作的包,可以说,Excel所有能实现的功能,pandas都可以通过代码轻松实现,因此,pandas对于Python学习非常重要。

导入库

import pandas as pd

数据类型

根据实际场景,Pandas支持两种类型的数据结构。

  1. Series

  2. 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箱

  • 为什么要分箱?

  1. 离散变量便于特征的增加和减少,便于模型快速迭代

  2. 稀疏向量内积乘法更快,计算结果便于存储,容易扩展

  3. 离散化后的特征对异常数据有很强的鲁棒性,例如,连续异常值5000可能对模型影响很大,但如果分箱后,模型影响很小

  4. 为模型引入非线性,提升模型表达能力,加大拟合

  5. 模型更加稳定,不会因为各别数据增加而影响模型精度

  6. 简化模型,防止模型过拟合

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))
01234
00.6717850.8794040.3504730.6896890.857887
10.7108170.4956260.3612290.6832980.872921
20.6231850.2451170.2815890.5311990.893249
30.3732950.4326490.8427310.1275290.713869
40.0386100.6413080.9030390.8291210.395986
50.7740260.8562680.1842180.0582890.145508
60.7580300.4952850.8679130.4117900.781194
70.2451900.6186230.7380770.3008380.992442
80.4926210.7235530.9580070.8341200.618777
90.9443070.8771470.1750410.0585990.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()
RankTeam/NOC金牌SilverBronzeTotalRank by Total
01United States of America3941331131
12People's Republic of China383218882
23Japan271417585
34Great Britain222122654
45ROC202823713

改变行索引列的名称

data.index.name = 'ye'
ye
01United States of America3941331131
12People's Republic of China383218882
23Japan271417585
34Great Britain222122

每列的数据量

我希望统计每列数据有多少行,如果在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])
RankGoldSilverBronzeTotalRank by Total
0.2524.00.00.01.02.023.0
0.5046.01.01.02.04.047.0
0.7570.03.04.05.011.066.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()
RankTeam/NOCGoldSilverBronzeTotalRank by Total
9286Syrian Arab Republic001177
6566Colombia041542
6667Azerbaijan034733
6768Dominican Republic032542
6869Armenia022447

每列的求和

求每列的值的总和,例如,整个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()
RankTeam/NOCGoldSilverBronzeTotalRank by Total
01United States of America3941331131
13United States of AmericaPeople's Republic of C...7773512013
26United States of AmericaPeople's Republic of C...10487682598
310United States of AmericaPeople's Republic of C...1261089032412
415United States of AmericaPeople's Republic of C...14613611339515
........................
883965United States of AmericaPeople's Republic of C...34033839810763737
894051United States of AmericaPeople's Republic of C...34033839910773814
904137United States of AmericaPeople's Republic of C...34033840010783891
914223United States of AmericaPeople's Republic of C...34033840110793968
924309United States of AmericaPeople's Republic of C...34033840210804045
 # 累计积:切忌不能放入字符串进去,必须为可计算的数值
 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]

筛选特定数据框

  1. 筛选第n行第m列的数据框

  2. 筛选第~行第~列的数据框

 # 返回第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()

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值