一文上手sklearn机器学习库 - 知乎 (zhihu.com)

Pandas工具简要介绍

image-20220908200620176

image-20220908200638089

append()

image-20220908200712630

join()

image-20220908200738425

concat()

image-20220908200814352

merge()

image-20220908200903780

pivot_table()

image-20220908201010241

窗口操作 image-20220908201119621

工作职位展示

image-20220908201325868

Pandas简介

image-20220908202022424

image-20220908202119266

image-20220908202146066

image-20220908202217203

image-20220908202331038

Series & DataFrame

image-20220908202436952

image-20220908202502773

read_excel()参数介绍

image-20220908204235731

选择子表

image-20220908204447740

指定表头

image-20220908205021679

image-20220908205628776

image-20220908205605044

指定使用列

强烈推荐str-list

image-20220908210136016

获取str-list小彩蛋

image-20220908210315046

对其ctrl c

image-20220908210343553

将不要的名字删除,再使用split函数

image-20220908210542096

最后cv,一键得结果

image-20220908210625490

跳过不要的行

跳过不要的列已经给你了usecols这个参数了,所以也无需单独设置

image-20220908210724840

设置列名

image-20220908211038659

定义列名和类型

image-20220908211251300

dtype类型大全

一般来说int65, float64,bool,datetime64[ns],object系统可用推导出来,别的可能就要求手动了

image-20220908211319679

str与string的区别是,str默认保存为object对象

image-20220908212339477

另外像季节品牌这些比较少的量可以设置为category,种类有两种好处

  • 节约内存
  • 方便自定义排序

我们设置dtype的目的是:不同类型的数据,有自己的一套函数,我们为了方便操作,因此得改变数据类型

自定义日期解析

parse_dates是动词,解析日期,date_parser是名词,日期解析器

image-20220909095501762

parse_dates

不是True,False,就是列表,字典,不能单独传入一个列名,要加列表的括号

image-20220909100344083

将分开的年月日类型拼接成一个日期类型

image-20220909100615936

image-20220909100651139

image-20220909100739839

parse_dates的作用就是如此立竿见影

image-20220909100042738

日期替换年_月_ 日

image-20220909100231284

date_parser

其中一个 x 就是一个series

image-20220909101457278

image-20220909102754555

处理缺失值

image-20220909103011140

image-20220909103051258

实践

​ 我们来说明一下数据,首先第二行第二列是一个空格,这样的格式显然是不规范的,是一个小坑

image-20220909103300180

​ 我们只需要在na_values里输入一个列表,就可以把我们想要替换成缺失值的替换出去。

另外。下图excel表格中#N/A与#NA是默认会被解析为NaN的字符串

image-20220909103417266

​ 更多的,我们还可以传入一个字典进入na_values,指定我们想要替换的列(如果有想要替换的行直接转置就完事了,完全不麻烦)

image-20220909103729018

值转换(+-*/)

image-20220909104054303

Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。

注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。

lambda x: x.strip() 也可以写成 str.strip

image-20220909104233001

若要去除中间空格:

1、使用字符串函数replace

1
2
3
1 a = 'hello world'
2 a.replace(' ', '')
3 # 'helloworld'

2、使用字符串函数split

1
2
3
1 a = ''.join(a.split())
2 print(a)
3 # helloworld

3、使用正则表达式

1
2
3
4
5
6
7
1 import re
2 strinfo = re.compile()
3 strinfo = re.compile(' ')
4
5 b = strinfo.sub('', a)
6 print(b)
7 # helloworld

4、int(对于数字)

1
2
3
4
5
6
content = input("请输入内容:").strip() #可输入1 + 3
# print(''.join(content.split()))
index = content.find("+")
a = content[0:index]
b = content[index+1:]
print(int(a)+int(b)) #转化以后,自动去除空格

字符串转bool

只有一列全都转换,他才会转换成功,因为d为false,但是e、f没有在列表中,所以转化失败

image-20220909104847323

不过xxx_values无法对数字类型使用,要转换可以用之前讲到的dtype

image-20220909105312619

其他参数补充

指定index

image-20220909105427608

是否转换数据为series

image-20220909105458865

是否重命名列

image-20220909105556928

指定解析行

解析不包括表头,从表头下一行开始,如果包括表头,就是三行

image-20220909105638367

字符串文本解析为数字

image-20220909105756176

是否转浮点类型

image-20220909105956630

to_excel()参数介绍

image-20220909110204567

是否输出行索引

image-20220909110320017

即在’tb.xlsx’后面加上, index = False/True

同时我们也可以给行索引加上名字,也就是dataframe.index.name

image-20220909110652280

命名表名,规范float格式,设置空

image-20220909111111893

image-20220909111241092

ExcelWriter()参数介绍

他的优势就是可以输出两个表到同一个文件中

image-20220909111438784

image-20220909111528680

假如不传datatime_format,那么输出默认就是

image-20220909111930198

但实际工作中一般是不想看到这个时分秒的,但这都是看个人的需求了。

写/读csv

image-20220909113451643

默认采用index=False,不然读出来就不是标准格式了image-20220909114106434

image-20220909113751619

标准读出以后:image-20220909114228303

也可用sep指定分隔符image-20220909114333179

image-20220909114352686

读写pickle文件

​ pickle是一个二进制文件,用于将原本的xlsx或者csv文件转成机器语言,从而几百倍的提高读写效率,相当于一个全局变量,所以我们以后几乎就可以直接使用pickle来进行操作,从而最大成本的节省我们的时间,并且与直接读写csv效果是完全一样的。

image-20220909152118545

效果立竿见影

image-20220909152935790

pandas + sql

我们需求:实现这样一个功能,将本地的excel表格存放到mysql中,如果还有2021年的数据,也同样创一个新的库

image-20220922110656710

1.安装依赖

image-20220922111621694

2.造库造表

image-20220922111528206

3.创建引擎

image-20220922111910540

读写执行sql语句

image-20220922113636511

to_sql

相关api

chunksize是为了避免你的内存装不下,每一次批量读取

if_exists的replace慎用,他会删除你的表并且创建一个新的表,尽量不用

​ append参数很常用,也就是把你当前dataframe的内容一行行追加到表中

​ fail是提醒你之前是否存在该表,如果已经存在这个表就报错

image-20220922113851130

实例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pandas as pd
from sqlalchemy import create_engine

# 创建引擎
con = create_engine(
"mysql+pymysql://root:123456@localhost/sales2020"
)

# 读表
df = pd.read_excel('jd.xlsx')
print(df)

# 中文表名改为英文,应该和原表的英文名对应,插入会报错
df = df.rename(columns={'货号': 'goods_id',
'日期': 'date',
'销量': 'volume'})
print(df)

goods_id date volume
0 YZFM1200 2020-01-01 2
1 FLHR1800 2020-01-02 5
2 LCHM9800 2020-01-03 8
3 HWLA4700 2020-01-04 6
4 UQNA9200 2020-01-05 10

# 两种形式均可写入sql
# pd.io.sql.to_sql(df, 'jd', con=con, if_exists='append', index=False)
# df.to_sql('jd', con=con, index=False, if_exists='append')

read_sql

参数说明:

第一个参数为选择表名或者直接输入语句吗,

con为选择引擎

columns可以选择列名,但是如果第一个参数是语句,则该句无效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pandas as pd
from sqlalchemy import create_engine

con = create_engine(
"mysql+pymysql://root:123456@localhost/sales2020"
)

# 1: 传入表名
df = pd.read_sql('jd', con=con,
columns=['goods_id', 'volume'])
print(df)


# 2: 传入sql查询语句
df = pd.read_sql(
'select goods_id,volume from jd where volume > 5 order by volume',
con=con)
print(df)
goods_id volume
0 HWLA4700 6
8 LCHM9800 8
23 UQNA9200 10

mysql执行

1
2
3
4
5
6
# 很简单,执行语句只需要用execute套住mysql代码就行。
con.execute("insert into jd values (50 ,'aaa','2020-01-10',100)")
# con.execute("delete from jd where volume=100")
# con.execute("update jd set volume=1000 where goods_id='UQNA9200'")

# con.execute("update school.students set 成绩=10 where id=1")

index索引

image-20220909161131997

image-20220909161216526

识别

​ 通过每一个格子的索引,我们可以知道他具体代表的含义

image-20220909160350349

对齐

​ pandas在操作之前,会根据索引,自动帮我们将同一类型的实物对齐,例如下面这两个series是没有对齐的。

image-20220909160430530

所以相加之前,会将同类型的对齐,这就是索引对齐的作用

image-20220909160536608

上下左右也同理,先对齐,在拼接

image-20220909160826296

image-20220909160903270

获取和设置

image-20220909161020989

查看dataframe基本信息

image-20220909163402236

info()

打印摘要:如果有列显示的数字比244要少,那么他就是有空值,这里就没有空值

image-20220909161645469

describe()

描述性统计信息:只统计数字类型,非数字的不会统计

image-20220909161858302

其中,std为样本标准差

image-20220909162012304

什么是样本标准差

​ 举个例子,全国成年男性的身高是一个总体,我们想知道身高的标准差。最准确的测量办法就是对所有男性进行身高测量,然后求平均值,然后按照公式变换,最后除以n。

​ 但是,测量全国所有男性身高几乎是不可能的事,或者说成本太高。

​ 可我们就是想知道这个总体的标准差怎么办?

​ 我们可以进行抽样,按照抽样规则,选取合适的样本量,抽取一定数量的男性测量,这个就是样本。可以肯定的是,样本的数量会比总体小很多(如果不是这样,那么抽样就没有意义)。测量样本的身高就要比测量总体简单多了。

​ 对每个样本进行测量,得到身高用于计算标准差,那么这个标准差就是样本标准差。

25%

计算方法:,在这里就是只看1,2,然后再把2 - 1最后得到的这个1 * 25%,用 2 - 0.25即是最后的结果1.75

image-20220909162749532

to_numpy()

将数据转化为numpy形式

image-20220909162946283

其余一些参数的测试

columns查看列索引,values转化为numpy,tolist转化为列表。

image-20220909163442302

image-20220909163243939

Series查看数据基本信息

这些都和dataframe的大同小异

image-20220909163536475

检查唯一性

image-20220909163704945

方法展示

返回唯一存在的值

image-20220909163813398

image-20220909163923715

assert

assert函数相当于一个断点的功能,保证函数的参数是唯一的

image-20220909164117576

检查长度

image-20220909164253717

image-20220909164310386

检查空值

image-20220909164352921

空值加法也会变成空值,因此我们必须处理掉空值

image-20220909164608634

image-20220909164551629

dick-like选择数据

series转dataframe:series.to_frame().reset_index()

image-20220909165053119

mask选取

​ 在实际生活中我们时常需要这样的取法,因为我们可以通过条件来生成mask,并且注意,如果我们以[ ]的方式来取数据,则是series,想要取得dataframe,就[[ ]]就行,再另外,注意观察[[True, False, True]],首先数量是一样多得(不一样就报错),和行数,其次,为True的才显示,我们可以利用这个来筛选很多的数据!!!

image-20220909170316319

我们先创建掩码,选择我们想要的数据,得到以后就可以进行进一步操作(s为series列表)

image-20220909170732837

当然我们也可以直接在括号中使用,跳过生成掩码这一部分

下面这个的意思是,取B这一列,返回数据中大于2,小于6的那一行

image-20220909171021197

取反

image-20220909171200709

list-like切片选数据

值得注意的是,数字切片左闭右开,字符串切片边界全取,另外切片都是切的行,=-=列通常都是读取数据后就选好了的吧

image-20220909171533166

loc选数据

取行可以不提列,取列必须提行

loc –> location

image-20220909171911387

一个值得关注的点,:代表选中全部 ::-1代表选中全部,但是倒过来

image-20220909172700223

甚至还可以给定步长 :: 2代表两步取一次,其实::-1的话,也就是每一步是-1,不断走,也便是倒序了

image-20220909172813440

iloc选择数据

i 就是integer,他和loc唯一的区别就是,iloc通常使用整数索引,这样使用的时候是不包括最后一个标签的,但是loc使用的时候包括最后一个,别的没变化。另外,loc适用范围广得多,iloc只能使用整数标签。

image-20220909201854562

Mutilndex多层索引

读写多层索引excel表

index_col基本能满足要求,但还是有所不足

image-20220909202936385

如果列索引(销量)有名字的话,就显示在他左边的空格中。

​ 这里,简单的读取,乍一看没问题,但其实我们可以发现发现,他把货号当成了列索引的名字,并且行索引没有名字,因此我们需要做一点小变动,具体就是df.index.name = '货号' & df.columns.names = [None, None]

image-20220909204115266

这个才是标准格式

image-20220909204741441

创建多层索引

相邻两个相同,excel展示的时候会自动合并

list-like创建法

image-20220909210956210

笛卡尔积创建

a集合和b集合,以有序的方式一一对应合并,最终组成的大集合称为笛卡尔积

image-20220909211137854

image-20220910160118307

此外更多….

image-20220909211242338

已有表格基础生成Multindex

在数模中,我们提炼二级指标说不定就可以用这个

自定义生成随机样本

image-20220909211852063

  • sample()函数,n为生成的多少,replace为取出后是否放回,前面调用它的series的items就是原材料

image-20220909212100083

采用随机采样快速填充结果

groupby快速分组yyds

image-20220909212255776

透视表等等在学!

image-20220909212439587

无敌!

多层索引取值

​ 这个看看就好了!大概意思就是这个,有个注意点是,这种多层索引都是采用字典机制,所以,我们传入参数是(‘淘宝’,’M’)这样的形式

image-20220910111621995

image-20220910111552512

slice(None)的意思就是选择全部,不能用:

image-20220910112023626

image-20220910112149590

数据赋值

image-20220910112410007

直接loc改也同样有效哦

image-20220910112659468

总之一句话,灵活选择,务必记住loc是先行后列

image-20220910113216674

缺失值

python中缺失值的类别

image-20220910113250362

让我们来观察一下空值都长啥样

image-20220910113443606

df.convert_dtypes()可以自动将空值转化为最可能的形式,最常见的是NaN

image-20220910113753406

检测缺失值

isna()/isnull() notna()/notnull() 相邻两行意思是完全一样的,输出的结果就是掩码,是空值的地方为True,其他是false

image-20220910114405073

删除缺失值

dropna()

  • axis = 0的意思就是选中行,也就是我们接下来的操作都是对一行一行的
  • how = ‘any’的意思是,只要哪一行有空值,无论一个还是多个,他都会进行删除 ‘all’的意思是必须这一行全部为空值,才进行删除
  • subset = None 的意思是检测所有的列,他可以传入一个列表,指定检测的列
  • inplace = False 这个参数在大多函数中都有,意义是是否就地操作,如果为True那么就是就地执行操作,没有返回值,如果为False就是新开辟一个空间,并且返回操作后的结果

image-20220910115042015

选中行删除,how为any,subset为None,inplace为False为系统默认

image-20220910115147412

填充缺失值

fillna()

  • value = xx 默认填充值
  • method = ‘ffill’(forward)为遇到空值默认向前查找对应的值来填充、‘bfill’(back)遇到缺失值默认向后查找值来填充,注意,这里的前后,当axis为0时,默认为上下;为1时,默认为左右
  • valuemethod是必须传一个,而且也只能传一个

image-20220910115921412

同时value也可以填入dataframe,此时,他找就是找行列索引,如果是一样的,那么才将这个dataframe的值填入对应dataframe

image-20220910120257414

image-20220910120927716

实际工作中最常用

image-20220910120617418

fillna只会填入空值(换言之,已存在的就不会填入)

image-20220910120802160

线性插值

interpolate(),他只利用了相邻的前后两点,别的没用。

image-20220910121117523

image-20220910121327145

数值运算

需要注意的问题

image-20220910153842970

image-20220910153949406

对空值的处理

两种方法均可,第二种是运算的时候默认换成0

image-20220910154042056

对除数为0的数

用1来代表任何数

image-20220910154156774

image-20220910154247750

Series不对齐情况

用add、sub、mul、div这些,将其fill_value = 0 可以在计算时补0,使得仅并集计算,不会爆NaN错误

image-20220910154900136

dataframe情况举例

image-20220910155349887

Muitindex实现

假如我们要将京东和淘宝的数据合并,并显示一个总需求,那我们应该怎么做呢?

image-20220910155656861

这里我们采用笛卡儿积的方式进行匹配

image-20220910160207453

image-20220910160255162

到这里我们使用join函数就实现了需求了

字符串

字符串操作

regex101: build, test, and debug regex

以下是最常用的一些:除此以外还有\w 匹配任意字符 \d 匹配数字 a+匹配延续字符

image-20220910161905999

在python中我们常常导入这样的包,然后就使用这几个方法。

image-20220910162221814

findall()

image-20220910162635943

注意,这个span,不是指找到了1、2,而是说match=1,它的位置索引是[1,2),也就是第一号的位置

image-20220910162721060

split()

以数字进行拆分

image-20220910162905025

这里使用r放在开头,表示他是一个原始的字符串,用[ xxxxx ]表示这里面的都需要匹配到,另外,如果再加一个参数为expand = True,那么series将变成一个dataframe

image-20220910165129363

image-20220910165300497

sub()

将\d找到的数字全部替换为*

image-20220910163006605

replace()

超过一个字符的,就视为正则表达式

image-20220910165606990

cat()

image-20220910165729584

str取值与切片

image-20220910165944474

extract()提取

这里第一个参数传入一个正则表达式,注意是用括号括起来的,使用时必须有捕获组(capture group),其实一个括号括起来就代表一个捕获组,例如正则表达式(\d{4})-(\d{2}-(\d\d))这个正则表达式可以用来匹配格式为yyyy-MM-dd的日期

image-20220910170133718

另外(?Pxxx)这个是正则表达式的一个语法,可以给捕获组取到的东西命名

image-20220910170826749

contain()

在添加一个参数,na = False,即可将下图中转化为False

image-20220910170922121

get_dummies()获取独热编码

image-20220910171156678

count()/len()

image-20220910171341782

pad()填充

image-20220910171506945

image-20220910171532185

string类型

image-20220910163152969

推荐使用StringDtype,避免混淆的情况

访问器

使用之前必须保证调用元素都是string类型,不然可能出现一些意想不到的结果。

可以使用astype进行转换。

image-20220910163835999

image-20220910163447025

访问器应用实操

image-20220910164037140

第一列多加了空格,第二列最后为文本,第三列最后也为文本,但我们用pandas读入之后是这样的,数据量多了之后很难发现有什么问题

image-20220910164112622

如果我们应用了一个convert_dtypes()之后仍然发生数据类型对不上的情况,很有可能数据源就是有问题的

image-20220910164318336

这个时候怎么处理呢?

image-20220910164740983

时间

Time series / date functionality — pandas 1.4.4 documentation (pydata.org) 如果不知道有哪些时间类型,点我进入

时间类型

通常舍弃最后一个时间偏移量,用时间增量来代替

image-20220910172150949

时间点/时间段

image-20220910172337459

时间增量/时间偏移

image-20220910172516309

实例演示

Timedelta和DataOffset可以与其他时间点进行运算。

image-20220911094757780

1月1号加一个工作日变成了2号,这没问题,一月二号加两个工作日变成了六号,这是因为二号是周五了,于是他跳过了周六周日,再加了两个工作日到周二,也就是六号

image-20220911095145985

指定读入类型,但如果我们直接用convert_dtypes(),则会有可能Timedelta转换错误

image-20220911100010596

image-20220911100142513

转换时间序列

to_datetime()

image-20220911100254078

coerce转成NaT,也就是说,转换成功的转换,转换不成功的自动转换成时间类型的空值

image-20220911100318130

image-20220911100618610

生成时间戳范围

date_range()

image-20220911101248643

image-20220911101303236

B和C为取工作日 pandas date_range freq 可选值 - Tiac - 博客园 (cnblogs.com)

image-20220911101341075

image-20220911101349772

时间序列访问器

image-20220911104003661

属性

image-20220911104056919

方法

image-20220911104219007

Period创建

image-20220911104538525

image-20220911104546237

start_time、end_time是时间点,也就是后面有0时0分0秒那种

image-20220911104609628

Timetelta时间间隔

Timedelta()

image-20220911105126680

unit用法

image-20220911105256822

to_timedelta()

image-20220911105545532

timedelta_range()

image-20220911105656731

更多详情,请见pandas.Timestamp — pandas 1.4.4 documentation (pydata.org)

时间序列索引

优点

image-20220911110456841

image-20220911110348657

image-20220911110418360

image-20220911110552945

注意点

image-20220911110701199

image-20220911110808178

多表合并

append()上下合并

  • to_appendother名字不一样,但作用都是一样的,指定将要合并的表的类型
  • ignore_index是否忽略索引
  • verify_integrity是否检查有重复的行索引
  • sort对列名进行排序

image-20220911111302547

实例演示

我们关注这种没有对齐的情况,看看它是怎么操作的

image-20220911111618028

它创造出具有空值的对应列,然后将其append上下拼接

image-20220911111700075

当ignore_index=True时,索引就从1月、2月、3月变成0、1、2

image-20220911111818524

verify_integrity=True,为检查行索引是否有重复,如果重复会报错。如果设置为False会导致列名重复,多出重复列,默认为False

image-20220911111932966

sort设置为True,自动排序列索引,将这个BAC转换为ABC

image-20220911112003645

合并文件夹的表格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"""
使用 append() 函数
合并一个文件夹里面的全部表格
"""
import os
import pandas as pd


def v_concat_files(folder: str) -> pd.DataFrame:
df_all = pd.DataFrame()
for fn in os.listdir(folder):
ffn = os.path.join(folder, fn)
print(ffn)
df_temp = pd.read_excel(ffn)
df_all = df_all.append(df_temp)
return df_all


if __name__ == '__main__':
# df_A = v_concat_files(
# '/Users/Yi/Mirror/我的python教程/Pandas办公自动化/z_data_source/PlatformA'
# )
# df_A.info()
# print(df_A.head())
# df_A.to_excel('all_A.xlsx')
# df_A['平台'] = '平台A'
#
# with pd.ExcelWriter(
# 'all_A.xlsx',
# datetime_format='YYYY-MM-DD'
# ) as writer:
# df_A.to_excel(writer, index=False)

df_B = v_concat_files(
'/Users/Yi/Mirror/我的python教程/Pandas办公自动化/z_data_source/PlatformB'
)
df_B['平台'] = '平台B'
with pd.ExcelWriter(
'all_B.xlsx',
datetime_format='YYYY-MM-DD'
) as writer:
df_B.to_excel(writer, index=False)

join()左右合并

  • 第一个参数other就是将要与调用join方法的东西合并的东西
  • how参数指定合并的方式,默认是left(依靠左表) right(依靠右表) outer(依靠两个表, 并集) inner(依靠两个表的交集)
  • lsuffix和rsuffix就是左后缀和右后缀,它们的意思就是,如果合并之后有相同的列名,那么左边\右边的表格就会加上的后缀
  • sort是排序,它是对index进行排序,也就是对行进行排序,默认是False

image-20220911145438775

拼接series

image-20220911150045654

image-20220911150534192

拼接dataframe

how = outer、left、right、inner

image-20220911150833927

实例演示

下面是使用lshffix和rsuffix的实例

image-20220911151151362

join形成列表

image-20220911152045911

concat()左右/上下合并

  • objs:使用对象可以是列表/字典
  • axis=0 默认是append,进行上下拼接,1就是左右合并
  • join: 只有outer inner
  • keys的作用见下面,ignore_index 和 verify_integrity都为之前讲过的

image-20220911152138169

一次性读多表

每一次的储存形式就是列表

image-20220911152556028

image-20220911152706112

keys的作用

image-20220911152857146

当然,如果直接传入字典的话效果与上面这种一样,了解即可

image-20220911153117161

merge()联合

先来看一个简单的实例: 在工作中,可能时常会遇到,将两个表合并在一起,通过一定的索引什么的,这个时候就要用到merge()

image-20220911153551765

例如我们期望的样子就是下面这样

image-20220911153655384

1:1

image-20220911153836787

image-20220911153939870

就这种情况的话,用join(),append(),concat都可以很好得满足任务

M:1

image-20220911154058099

image-20220911154139644

M:M

同样也是根据KEY这一列来进行合并,拼接的时候是使用笛卡尔积的方式,也就是说,全排列。

image-20220911154207832

image-20220911154257864

image-20220911154343603

merge的on就是选择哪一列作为索引,别的join,append()都有这个参数,如果两个表格中,索引的名字不一样,那么可以这样,设置left_on、right_on,不过一般excel都可以移动位置,或者你直接去改一下名字就行了,没必要这么麻烦,就算合并起来了还不是要删除一列。

1
2
3
4
pd.merge(df1, df2,     
on='货号',
how='left',
validate='m:1')

image-20220911155343882

可能会遇到的问题

在电商平台我们可能会出现一个问题,右边的基础信息表,我们不小心出复制了一个牛仔裤,这样的话,如果merge,会导致销量这个本只应该是10的数字变成18

image-20220911160355896

image-20220911160534400

validate

在我们指定模式为多对一的形式,如果右边的索引出现不唯一的情况,就会报错,从而解决掉隐患

image-20220911161002215

使用列表共同匹配

image-20220911161711466

透视表

pivot()

pivot()呈现效果:

image-20220911161906361

image-20220911162330607

但是如果当出现重复数据。。。。pivot()表示无能为力,pivot_table()出场

image-20220911162037736

pivot_table()

image-20220911162212047

实例演示

image-20220911162702800

image-20220911162715585

如果不传入columns,那么就用values来当做列索引

image-20220911163340544

另外,对不同的value做不同的处理,用字典来传入方法

image-20220911163444430

这次我们加上columns

image-20220911163623980

甚至列名还可以调用时间的迭代器,这里采用了季度来统计

image-20220911164013023

聚合函数

1
2
3
4
5
6
7
8
9
"""
aggfunc: aggregate function
聚合函数
求和: sum, 'sum', np.sum
求均值: 'mean', np.mean(默认)
最大值: max, 'max', np.max
最小值: min, 'min', np.min
数量: 'count'
"""

从某种意义上来讲,pivot_table()能满足你的所有需求

排序

image-20220911170207887

sort_index()

axis=0时,他根据索引大小进行排序,如果是axis=1,就是根据列名进行排序

image-20220911164530614

image-20220911164612030

ascending

ascending参数默认为True,就是升序的意思,我们设置为False,就是降序输出

image-20220911165953889

soft_values()

axis=0时,对A列的所有行进行排序

image-20220911164657954

image-20220911164800626

CateGoricalDtype()

image-20220911165809725

实例

我们做一个透视表操作,这是代码的默认排序

image-20220911170431283

现在我们用CategoricalDtype()来设置我们自己的顺序

ordered参数就是是否已经排好序,这里选择True

image-20220911171022632

用astype指定为自己的类型

image-20220911171133222

设置完类型之后再次使用透视表,即可得到想要的结果

image-20220911171328179

排序拓展

image-20220911171641345

分组

groupby()分组

image-20220911171834531

拆分多个组

PPT演示

image-20220911171930950

image-20220911172008810

image-20220911172155205

代码验证

image-20220911172406222

分组后操作

分组后一般进行的三种操作

聚合

直接压扁,总之返回一个新的dataframe

image-20220911172532188

转换

他的索引跟原来的dataframe索引是一致的,也就是说我们总是新增一列来接受转换后的结果,

image-20220911172647347

过滤

有几个注意点:

第一:使用之后分组的货号会被抹去,但找回来也很简单,直接根据索引即可

第二:filter筛选我们所需要的东西,这里是用的销量之和大于6的返回

第三:过滤就相当于删除某些行

image-20220911172922845

image-20220911174141263

重新加回货号

image-20220911174725183

聚合函数

groupby().agg() agg就是聚合的意思。

image-20220911175556988

first()

image-20220911175944854

nth()

image-20220911180030022

size()

返回一个series

image-20220911180107952

count()

返回一个dataframe,且所有的列都是货号的个数.

image-20220911180208278

字典传入

同样可以配合字典处理

image-20220911181503821

分组条件是否做索引

as_index 字面意思。

image-20220911181610956

分组后自定义处理

理论上可以构建函数处理各种参数

1
2
3
4
5
6
7
8
def fun(df, s):        
print(df)
print(s)
def main():
df = pd.DataFrame([['a', 1], ['b', 2], ['a', 3]], columns=['name', 'age'])
s = '我是一个被需要的参数'
df.groupby(['name']).filter(fun, s=s)
main()
1
2
3
4
5
6
7
  name  age
0 a 1
2 a 3
我是一个被需要的参数
name age
1 b 2
我是一个被需要的参数

窗口

rolling()

image-20220911203107537

基本使用

image-20220911202912221

修改最小观测

如果不想前两个为空的话,可以利用min_periods参数,指定最小观测范围

image-20220911203016098

修改对齐方式

如果希望居中对齐的话。设置:center=True

image-20220911203226452

修改窗口权重

win_type() (19条消息) DataFrame加权滑窗rolling使用,win_type=‘triang‘详解_条件漫步的博客-CSDN博客

image-20220911203540162

窗口取值范围

offset参数传入2D,他就从当前往前找,直到找完这一天和上一天的

image-20220911204410259

扩展窗口

expanding(), 没什么特别,扩展窗口求和而已。

image-20220911204554027

image-20220911205204768

我们用代码来实现这个需求。excel也可以excel 递增求和你会吗?excel 递增累计求和技巧_office教程网 (office26.com)

image-20220911205333915

image-20220911205644338

image-20220911205652996

更多实用函数方法

将已有列设置为index

set_index()

image-20220911205833900

转化为下图所示

image-20220911205848617

keys,第一个参数,可以放列名,还可以放个列表啥的,都行都行

drop,默认为True,也就是删除set_index原有的列,将其转移到index上,若为False,结果如下图所示

append,是否将该列名追加于原来的index之后,默认为False,若为True

image-20220911210134125

image-20220911210249874

转换index为列

image-20220911210610278

image-20220911210642684

drop即将索引丢弃,level是指你想要设置那一层的索引

image-20220911210835110

col_level是多少就是说这个新索引的名字出现在列索引的第几层

image-20220911211052817

自定义列名重组

​ reindex() 对于下面这个dataframe,他的title为 c b e,不包括a,那么会删除a列,然后将顺序改为c b ,将不存在的e列用NaN补全

主要作用:无论你df以前是什么顺序,我一步就设置成我要得顺序

image-20220911212109454

image-20220911212224062

下面代码,index=可写可不写

image-20220911212330419

image-20220911212607391

像df2一样

reindex_like()

主要作用就是将df1的格式替换为df2的行列格式输出(数据还是用df1的,只抄格式)

image-20220911212813650

重命名索引

我认为直接excel改

image-20220911213013112

也可以传level参数

image-20220911213037396

where条件选择数据

pandas.Series.where的返回结果,先用条件筛选,筛选掉的位置用other来填充(通常选择numpy类型的,舍去这种)

image-20220911213325245

numpy的where在这里可以和pandas混合使用。

image-20220911213512224

现在我们有一个需求,就是搞活动促销,我们想要知道我们实际收款是多少,那么,用where可以轻松解决问题。

image-20220911213905760

image-20220911213825220

numpy下的where也有他的用武之地,实际工作中使用np.where会更通用,也更常用!!

image-20220911214119300

根据区间分类

注意cut()方法: 左闭右开

image-20220912110326207

image-20220912110456055

参数列表:

x:可以是一个series也可以是一个列表,一定要是一维

bins:箱子的意思,就是箱子是如何分类的,将想要分离的间隔值写入一个列表或者直接写入一个数字,这样的话就等距分隔

include_lowest:将间隔的最小值减去一点点,然后包括最左端的值

right:默认为True,如果是False的话范围取值不包括区间右边的端点,此时如果取False,无需更改include_lowest参数

labels:将你定义的区间,显示数字从区间范围变成你定义的labels

precision:保存的精度,也就是小数点后多少位

image-20220912111204538

image-20220912111058749

image-20220912111313530

标记重复值

first:第一次出现重复开始,才标记为True,默认也为first

image-20220912111515968

last:用倒序,从后开始记录重复

image-20220912111624674

如果keep=False,那么直接就标记重复的值

image-20220912111704665

丢弃重复值

drop_duplicates,这也是为什么参数叫keep的原因,保留第一个,或者保留最后一个,或者都不保留

image-20220912111819912

dataframe同时观测两列,那么就以两列的数为基准,当两列两列的出现重复才删,例如这里,2、6;2、6

image-20220912112521361

随机取样

sample()

image-20220912112903066

n:就代表取多少个数值

replace:设置是否有放回,默认False(无放回)

frac:取0-1的小数,就是取值个数占所有数的比例,例如总共五个数,传入0.8,则返回4个数。

weight:取到每个数的权重概率,这个就是传入一个有n个数字的列表就行,他会自动把列表进行归一化,总之就是取值越大,越有可能获得,当然,手动归一到0-1之间,会更加直观

random_state=xxx 设置随机种子,也就是把每次的结果固定下来

axis:主要针对于dataframe,如果是0,则取xxx行,如果是1,则取xxx列,也就是随机抽取

image-20220912113351626

image-20220912113724644

重新采样

resample

image-20220912113953886

image-20220912115904464

为每一个时间戳生成一个1-6的随机数,然后用重采样对他进行处理!

image-20220912114203329

实例

例如对这张表的数据进行重采样统计

image-20220912114649736

通过重采样,并且sum求和函数,将所有数值类型的量进行统计

image-20220912114803387

同时,当然也可以对其进行字典分组操作.agg

image-20220912114946680

将日期列定义为时间类型,但不定义为索引,我们也可以通过on参数来进行指定重采样的索引

image-20220912115323630

apply()应用函数

我们着重讲Series.apply(),其实这些都可以调用,只不过逻辑一样

image-20220912150131933

apply可以代替聚合和转换功能

image-20220912150252120

传入参数为函数

image-20220912150349527

运用过程

传入python func

image-20220912150427791

所以我们就可以知道传入一个python函数,他会对series的参数进行逐个传入。

args:传入额外的参数

image-20220912150722224

image-20220912151332726

也可以直接用y=,z=,这样更直观一点

image-20220912151444194

axis=0时,设置垂直计算

image-20220912151555245

以下是apply调用numpy函数的演示

image-20220912150531368

另外,’sum’代表传 入一个numpy方法,如果直接sum的话叫做传入了一个python的内置函数,会引发报错,报错内容就是说int不是一个可迭代参数

image-20220912151029606

排名

rank()

image-20220912151750888

以下是对series([7, 8, 8, 8, 9])的各种排名操作,方法默认使用average,我们实际用dense和first居多

image-20220912151931539

参数列表:

method:选择方法

ascending: 默认升序,改成False可以为降序

numeric_only:只对数字类型进行排序

na_option:对空值的处理办法默认是'keep'有{‘keep’, ‘top’, ‘bottom’} top bottom就是指把空值的排名定位于第一还是倒数第一

pct:百分位的排名

ps:若排序结果为浮点型,用convert_dtypes()可以改变为整型

image-20220912152120429

dataframe演示,实现先对id进行分组,然后对value列进行排名

image-20220912153218478

堆叠

列索引堆叠于行索引

stack() 把列索引堆叠到行索引列

image-20220912153354867

参数列表:

dropna:默认为True,就是丢掉数据里的空值

level=-1,默认为是列索引最下面那一层,0就是倒数第二下面的,在这里,-1就是i、j

image-20220912153447873

image-20220912153720564

行索引反堆叠于列索引

unstack() 反堆叠 (index -> columns)

和我们想的也一样,level = 0这一层要外面一点。

image-20220912154029325

max/min

idxmax/min

idx,依照id来顺序访问,找到第一个idx的最大值/最小值

image-20220912154257045

image-20220912154326701

argmax/min

arg找的是数字索引,所以会返回21

image-20220912154353919

image-20220912154433075

nlargest/nsmallest

nlargest(1) nsmallest(1)、返回的是series

image-20220912154612070

image-20220912154636655

image-20220912154839918

查询并筛选行

query() ,他的好处是可以链式查询

image-20220912155256885

但当列表名为c c,我们需要特殊处理就是加 `c c`

还有就是如果要传入外部变量,需要在布尔表达式中,该变量前加 @

image-20220912155422221

列名转化为数据

melt() 逆透视

image-20220912155549610

参数列表:

逆透视中只有value和variable,分别是变量和参数的意思

id_vars:就是选择不改变格式的列,也就是输出的结果,该选中列不会发生改变,充当索引,填入列名或者列表的列名

value_vars:选取xx列的变量,填入列名或者列表的列名

用var_name和value_name就是重命名列名,好理解。

image-20220912155620795

image-20220912160218396

错位相减

diff() 传入的数字为偏移量,默认为1,也可以传入负值,就换成向上移动

image-20220912160452732

dataframe也是一样的

image-20220912160636229

偏移数据/时间索引

shift()

1
2
3
4
5
6
7
##### Series/DataFrame/GroupBy
##### shift() 偏移数据, 偏移时间索引
- periods: 指定偏移量(偏移位数,可为负数)
- fill_value: 填充空值
- freq: 指定为偏移时间索引
1. "D", "W", "M", "infer"
2. DateOffset, BDay, Timedelta

freq与periods混合使用效果更佳哦

image-20220912161244496

BDay就是说偏移之后的结果都不会包括周六和周日

image-20220912161701351

百分比变化情况

Series/DataFrame/GroupBy

pct_change() (Percentage change) 百分比变化

  • periods: 偏移量 (例如原来该第二个减第一个的,你设置periods为2,则是第三个开始,减去第一个)

  • freq: 频率(时间索引)

    1. “D”, “W”, “M”, “MS”, “B”
    2. DateOffset, Timedelta
  • limit: 最多连续填充空值个数

这个是怎么计算的呢?,(2 - 1)/ 1 = 1 (3 - 2) / 2 = 0.5 所以这一列就相当于原始的数据源百分比的增长情况

image-20220912162100495

limit用法,limit设置为1,他只从上到下填充了一个空值

image-20220912162543153

image-20220912162744521

更新

update()

image-20220912163147168

简单说就是替换!用右边的数字来替换左边的数字,是就地修改

image-20220912163234607

不过,如果右边的表内,该位置数字为空,那么左表保持不变

image-20220912163416404

如果需要用series修改dataframe的值,那么需要设置name和index,不然无法对应到位置

image-20220912163529247

数据可视化

支持图的种类

问号快速查看帮助文档

image-20220912170123636

image-20220912170145953

line:直线图

image-20220912170243496

bar:条形图

image-20220912170324667

barh:水平条形图

image-20220912170401531

pie:饼图

如果series有一个名字,None就会显示他的名字

image-20220912170423081

scatter:散点图

image-20220912170513010

hexbin:六角箱图

颜色越深的地方,六角箱图包含的个数就越多

image-20220912170554339

hist:直方图

某个区间的数值所出现的频率

image-20220912170657042

kde:密度图

randn是符合正态分布的,rand不是

image-20220912170745390

如果求落在某一区间的概率,那么可以转化为求他的面积,因为总面积一定为1

image-20220912170842367

密度图与直方图的比较

image-20220912171006870

box:箱型图

注意是rand

image-20220912171236525

如果有一个点,超过了箱子的2.5倍,自身+自身的1.5倍,那么、就称呼这个点为异常点

另外图上绿色线那里,就是数据最多的位置

image-20220912171342829

area:面积图

image-20220912171517112

matplotlib.pyplot()

通常绘图都是在Axes(坐标系)来绘制的,一个Figure可以包括多个Axes,Axes是Axis的复数哦

image-20220912171846112

准备阶段

1
2
3
4
5
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

image-20220912172115236

figure()

参数列表:

facecolor,边框的颜色风格

figsize:默认6 * 4(600 * 400),可以调整尺寸

dpi:越大越清晰

image-20220912172241570

pyplot-style

实际使用时建议风格二选一

还有一些值得注意的参数:

title:标题而已啦

ylabel,xlabel:设置x、y轴索引 可传入参数fontsize设置字体大小,color设置颜色等等,具体就到时候再搜,有一个以前一直不知道的可以设置的参数,将y轴转正,为rotation=0,还有将这个label往外往里移动的,labelpad

xlim,ylim:限制x、y轴取值,传入列表,输入左右两端的值即可

xticks:同样传入列表,具体见下图

grid:是否使用网格

legend:显示每个plt的标签 一个参数 loc= 就是legend的位置,默认是自动选取最好位置

image-20220912173052960

gca:获取当前坐标系,下面这种调用形式设置主次刻度

image-20220912173248085

OO-style

其实大部分情况就是把plt.xxxx调用换成面向对象获取到的轴来调用,这里的话就是用ax.xxxxxx

image-20220912173516159

image-20220912173605098

绘制多图

image-20220912173751343

一般来说,下面这种绘图方法,使用面向对象,不适用plt

image-20220912173956841

tight_layout()使得均匀分布,不会让大小与其他图碰上

image-20220912174011918

面向对象的形式

image-20220912174303275

nrows、ncols,多少行列的大图(每一行,每一列,都有几个小图)。

sharex和sharey,是否共享x/y轴。

facecolor:背景白色。

figsize:大图的尺寸 例如10 * 8(1000 * 800)

image-20220912174707204

image-20220912174805271

rcParams全局参数

Customizing Matplotlib with style sheets and rcParams — Matplotlib 3.5.3 documentation这里是可以设置的参数

image-20220912194536784

colormaps

colormaps,cmap,cm:颜色表

# https://matplotlib.org/examples/color/colormaps_reference.html颜色大全,使用里面的名字传入就行![image-20220912195332370](python+excel/image-20220912195332370.png)

available显示他的可选参数

image-20220912195154471

image-20220912195409589

也可自定义colormap

image-20220912195442276

设置颜色、线条、点样式

color

image-20220912195539213

image-20220912195605915

image-20220912195620323

image-20220912195638748

image-20220912195646682

marker

image-20220912195708420

line

image-20220912195745021

seaborn

seaborn: statistical data visualization — seaborn 0.12.0 documentation (pydata.org)

seaborn多图绘制seaborn学习笔记(五):绘制多子图 - 奥辰 - 博客园 (cnblogs.com)

load_dataset()

默认有一些可供练手的数据集

image-20220912200216512

set()

这是默认画出来的图的风格

image-20220912201327073

我们在画图之前set一下,会输出seaborn默认的风格和参数

image-20220912201407118

image-20220912201734465

context可选值仅有{paper, notebook, talk, poster} 主要改变的是x,y轴字体的比例,他们的比例是**{0.8 1 1.3 1.6},不过通常用font_scale**=1.6这样直接替代比较直观

style: {darkgrid,whitegrid,dark,white,ticks}

palette(调色板):推荐使用mutedimage-20220912202122305

rc:可以覆盖以上所有,所以肯定不会用,没这需求

seaborn图例关系

image-20220912202613757

关系图

image-20220912202807108

分类图
散点

大同小异,左边加了一些随机抖动,右边绝对不会重叠

image-20220912202901008

分布

超过上界和下界的都可以看做离群点,小提琴图可以看做是密度图和箱型图结合在一起

image-20220912203032442

估计

箱型图的那条线,表示的是一个置信区间,就是有95的概率落在这条线内(可以自定义),中间这个图,长方形最上端表示的是这个数据的均值位置,右边那个图,是指数量的累加,自然就无均值的意思

image-20220912203324816

分布图

双变量多出来的那两块可以指定为直方图,也可以指定为密度图

image-20220912203515282

重点

image-20220912203612646

Olympic实战

数据集介绍

image-20220912204731017

image-20220912204814740

合并检查数据

我们合并两表,并且发现数据集height和weight比起别的少了许多,又因为基数很大,所以把缺少的地方都删掉,并将其存放于一个变量

image-20220912205212879

删除完毕后

image-20220912205343926

散点图绘制

scatter进行绘图,发现数量太过于庞大

image-20220912205513137

进行筛选,仅显示CHN,RUS,USA,并且年大于2008,并对运动员进行去重image-20220912205640469

这样还是有6000多个点(没去重成功),最后再随机采样30个点,这样的话点数就会很少了

image-20220912205748364

最重要的一个参数是hue,语义的意思、颜色的语义,帮助我们分类,style,风格的意思,也帮助我们分类,区分点的类型,还有一个是size,使用一个数值来表示它的大小

image-20220912205854365

image-20220912210001237

image-20220912210033307

所以说一个表格最多可以传入五维的关系

如果我们换用relation图,然后kind设置为scatter,然后增加一个参数 col 甚至还可以增加一个维度!!!

image-20220912210309678

传入aspect,这个是设置轴的长宽比,这里设置为3:2,也可以设置整个图高度height,每一个高度代表72个像素

image-20220912210622352

对于语义参数,我们优先选用hue,因为style和size看上去没有hue那么明显。

image-20220912210846495

最后是一些花里胡哨的演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme(style="whitegrid")

# Load the example diamonds dataset
diamonds = sns.load_dataset("diamonds")

# Draw a scatter plot while assigning point colors and sizes to different
# variables in the dataset
f, ax = plt.subplots(figsize=(6.5, 6.5))
# despine()函数移除坐标轴
sns.despine(f, left=True, bottom=True) #默认舍弃了上右的坐标轴,这里参数为True,也舍弃了下左的坐标轴
clarity_ranking = ["I1", "SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"]
sns.scatterplot(x="carat", y="price",
hue="clarity", size="depth",
palette="ch:r=-.2,d=.3_r",
hue_order=clarity_ranking,
sizes=(1, 8), linewidth=0,
data=diamonds, ax=ax)

image-20220913094033185

线图

line:线图强调连续性,通常是时间的连续。也就是x是年,y是一个数值类型

最简单的画法演示,最外面浅色的是属于置信区间,实线就是平均升高

image-20220912211539871

下图体现出他是分组求均值再进行排序,并且如果数据出现空值,会双双删掉

image-20220912211942829

我们观察上上图,最后出现了锯齿状,是因为冬季夏季奥运会的缘故,因此用hue进行作图

image-20220912212119410

如果用relplot,可以使得图例跑到外面去,从而更加美观(另外新增了sex)

image-20220912212239617

条形图

两种方式均可

image-20220912213824279

image-20220912214048918

这个小点是置信区间,也可关掉,ci=False
另外order可以进行参数之间的排序

image-20220912214201802

数量条形图

这次我们对奖牌数量进行处理,用奖牌和年龄段进行分析,首先删掉所有None(没获奖的),转换类型,将奖牌对年龄进行排序,然后把x轴转换90度

image-20220912214716158

image-20220912214806380

所以可以看到运动员职业生涯的巅峰就在二十三二十四左右

选取拿金牌的人

image-20220912215025433

分析国家拿奖牌的情况,我们先进行去重,也就是对同一届奥运会,同一个事件,同一个奖牌,只保留一个,且只取1984年以后的数据来进行对比

image-20220912215225370

image-20220912215321234

排序中国和美国的奖牌数

image-20220912215604731

08年奖牌数

image-20220912215725766

我国奖牌数

image-20220912215825788

使用catplot展示

image-20220912215927336

箱型图

image-20220912220314846

首先用5个例子国家,和中国,定义出一个df,然后用这个df来演示箱型图,箱型图是适合于四分位的图,年龄,升高,体重都可以

image-20220912220439075

分析运动员年龄

image-20220912220547035

分析运动员身高,横过来就是xy数据交换就可以了

image-20220912220740539

密度图

image-20220912220903793

阴影shade设置为True就会有浅色阴影 ,普遍传入的是一维的数据,默认这样正着,如果你想把它倒着,那么有个参数vertical,设置为True即可

image-20220912221035655

*小提琴图

image-20220912221202799

操作全跟箱型图一样即可,就当箱型图用

image-20220912221313057

*分布图

之前讲过的KDE也是分布图

参数主要使用前五个

a:一维列表或者series

image-20220912221415608

image-20220912221607600

bins控制条的数量

image-20220912221841883

bins可以参考官方文档,可以设置为int或者字符串,字符串就是一些设置好的分箱策略,估计用不上吧,一般默认即可。

figure-level 和 axes-level

一个面下面可以有多个轴,下面的函数都是可以在上面的函数上运行的

image-20220912212502363

FacetGrid 方法
  • facet_axis(row_i, col_j): 获取指定轴
  • set(
    xlim,
    ylim,
    xlabel,
    xticklabels,
    ylabel,
    yticklabels
    title): 在每个子图轴上设置属性
  • set_axis_labels(): 设置轴标签
  • set_titles(): 绘制标题
  • set_xlabels(): x轴标签
  • set_xticklabels(): x轴刻度标签
  • set_ylabels(): y轴标签
  • set_yticklabels(): y轴刻度标签
    FacetGrid 属性
  • ax: 单轴
  • axes: 多轴(axes.flat)
演示

g 也就是seaborn下面的一个类。

image-20220912212851653

直接用lineplot画,比例会有一些不同,不过返回值就是完全不一样的。

另外,ci=None 关闭置信区间

image-20220912212954139

但如果我们对g进行一次g.ax操作,那么返回的就是那个轴

image-20220912213112141

取到子轴的办法

image-20220912213336632

设置标题label

image-20220912213530766

将轴传给自己,他将会继续在这个轴进行画图

image-20220912213633633

点图

使用tips展示,bar,line,point三合一展示

image-20220912220132389

加入了躲避dodge和置信区间ci

image-20220912220213016

也可以选择关掉

image-20220912220228931

热力图

heatmap:根据位置一一对应填数就行

参数列表:

annot:默认False,如果为True,将数字填在热力图表上

cmap:可以填matplotlib的colormaps,要选连续颜色的风格。颜色反转:xxx_r cool_warm是有对称颜色的,如果要设置的话,选择它

vmin、vmax:设置右侧value的最大最小值

fmt:显示字体的格式,比如'.2f'

center:选择右侧数值条的居中颜色是在那个数

cbar:默认为True,为False,则关掉右侧数值条

image-20220913092432010

他有一个用途,检测数据之间的相关性

在这里,越靠近一,那么就是正相关,越靠近-1,就是负相关

设置center在这里设和不设一样的,因为定位了最大最小值为1和-1了

这样做的目的就是说我不太关系0附近的点,我关心靠近1和靠近-1的点

image-20220913093355263

回归图

implot()

1
2
3
4
5
6
7
8
9
10
11
12
import seaborn as sns
sns.set_theme(style="ticks")

# Load the example dataset for Anscombe's quartet
df = sns.load_dataset("anscombe")

# Show the results of a linear regression within each dataset
sns.lmplot(
data=df, x="x", y="y", col="dataset", hue="dataset",
col_wrap=2, palette="muted", ci=None,
height=4
)

image-20220913102642142

高级颜色线图

relplot()

image-20220913104825790

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import seaborn as sns
sns.set_theme(style="ticks")

dots = sns.load_dataset("dots")

# Define the palette as a list to specify exact values
palette = sns.color_palette("rocket_r")

# Plot the lines on two facets
sns.relplot(
data=dots,
x="time", y="firing_rate",
hue="coherence", size="choice", col="align",
kind="line", size_order=["T1", "T2"], palette=palette,
height=5, aspect=.75, facet_kws=dict(sharex=False),
)

六面体+柱状图

image-20220913105430668

1
2
3
4
5
6
7
8
9
10
import numpy as np
import seaborn as sns
sns.set_theme(style="ticks")

rs = np.random.RandomState(11)
x = rs.gamma(2, size=1000)
y = -.5 * x + rs.normal(size=1000)

# color是绿色,hex是六边形
sns.jointplot(x=x, y=y, kind="hex", color="#4CB391")

马赛克+柱状图

image-20220913114407010

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import seaborn as sns
sns.set_theme(style="ticks")

# Load the planets dataset and initialize the figure
planets = sns.load_dataset("planets")
g = sns.JointGrid(data=planets, x="year", y="distance", marginal_ticks=True)

# Set a log scaling on the y axis
g.ax_joint.set(yscale="log")

# Create an inset legend for the histogram colorbar
cax = g.figure.add_axes([.15, .55, .02, .2])

# Add the joint and marginal histogram plots
g.plot_joint(
sns.histplot, discrete=(True, False),
cmap="light:#03012d", pmax=.8, cbar=True, cbar_ax=cax
)
g.plot_marginals(sns.histplot, element="step", color="#03012d")

堆叠直方图

image-20220913112308885

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt

sns.set_theme(style="ticks")

diamonds = sns.load_dataset("diamonds")

f, ax = plt.subplots(figsize=(7, 5))
sns.despine(f)

sns.histplot(
diamonds,
x="price", hue="cut",
multiple="stack",
palette="light:m_r",
edgecolor=".3",
linewidth=.5,
log_scale=True,
)
ax.xaxis.set_major_formatter(mpl.ticker.ScalarFormatter())
ax.set_xticks([500, 1000, 2000, 5000, 10000])

image-20220913113104687

箱型+散点图

image-20220913114240031
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="ticks")

# Initialize the figure with a logarithmic x axis
f, ax = plt.subplots(figsize=(7, 6))
ax.set_xscale("log")

# Load the example planets dataset
planets = sns.load_dataset("planets")

# Plot the orbital period with horizontal boxes
sns.boxplot(x="distance", y="method", data=planets,
whis=[0, 100], width=.6, palette="vlag")

# Add in points to show each observation
sns.scatterplot(x="distance", y="method", data=planets,
size=4, color=".3", linewidth=0)

# Tweak the visual presentation
ax.xaxis.grid(True)
ax.set(ylabel="")
sns.despine(trim=True, left=True)

丘陵密度图

image-20220913114650659

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})

# Create the data
####################改 x 改g list的个数 * 50(任意数字) = 500(任意数字)
rs = np.random.RandomState(1979)
x = rs.randn(500)
g = np.tile(list("ABCDEFGHIJ"), 50)
df = pd.DataFrame(dict(x=x, g=g))
m = df.g.map(ord)
df["x"] += m

# Initialize the FacetGrid object
#######################另外list多少个名字,这个10就改成多少
pal = sns.cubehelix_palette(10, rot=-.25, light=.7)
g = sns.FacetGrid(df, row="g", hue="g", aspect=15, height=.5, palette=pal)

# Draw the densities in a few steps
g.map(sns.kdeplot, "x",
bw_adjust=.5, clip_on=False,
fill=True, alpha=1, linewidth=1.5)
g.map(sns.kdeplot, "x", clip_on=False, color="w", lw=2, bw_adjust=.5)

# passing color=None to refline() uses the hue mapping
g.refline(y=0, linewidth=2, linestyle="-", color=None, clip_on=False)


# Define and use a simple function to label the plot in axes coordinates
def label(x, color, label):
ax = plt.gca()
ax.text(0, .2, label, fontweight="bold", color=color,
ha="left", va="center", transform=ax.transAxes)


g.map(label, "x")

# Set the subplots to overlap
g.figure.subplots_adjust(hspace=-.25)

# Remove axes details that don't play well with overlap
g.set_titles("")
g.set(yticks=[], ylabel="")
g.despine(bottom=True, left=True)

多维度密度聚类

这个例子好像是物种的长宽分布?

image-20220913140112002

1
2
3
4
5
6
7
8
9
10
11
12
import seaborn as sns
sns.set_theme(style="ticks")

# Load the penguins dataset
penguins = sns.load_dataset("penguins")

# Show the joint distribution using kernel density estimation
g = sns.jointplot(
data=penguins,
x="bill_length_mm", y="bill_depth_mm", hue="species",
kind="kde",
)

箱盒图

棱形方块就是离群点

k_depth:“proportion” 或 “tukey” 或 “trustworthy”
通过增大百分比的粒度控制绘制的盒形图数目。每个参数代表利用不同的统计特性对异常值的数量做出不同的假设。

scale:“linear” 或 “exponential” 或 “area”
用于控制增强箱型图宽度的方法。所有参数都会给显示效果造成影响。 “linear” 通过恒定的线性因子减小宽度,“exponential” 使用未覆盖的数据的比例调整宽度, “area” 与所覆盖的数据的百分比成比例。

outlier_prop:float
被认为是异常值的数据比例。与 k_depth 结合使用以确定要绘制的百分位数。默认值为 0.007 作为异常值的比例。该参数取值应在[0,1]范围内。

image-20220913140534260

1
2
3
4
5
6
7
8
9
import seaborn as sns
sns.set_theme(style="whitegrid")

diamonds = sns.load_dataset("diamonds")
clarity_ranking = ["I1", "SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"]

sns.boxenplot(x="clarity", y="carat",
color="b", order=clarity_ranking,
scale="linear", data=diamonds)

高贵蓝宝石密度图

绘制具有密度等值线的组合直方图和散点图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme(style="dark")

# Simulate data from a bivariate Gaussian
#################xy改成自己想要的就好了
n = 10000
mean = [0, 0]
cov = [(2, .4), (.4, .2)]
rng = np.random.RandomState(0)
x, y = rng.multivariate_normal(mean, cov, n).T

# Draw a combo histogram and scatterplot with density contours
f, ax = plt.subplots(figsize=(6, 6))
sns.scatterplot(x=x, y=y, s=5, color=".15")
sns.histplot(x=x, y=y, bins=50, pthresh=.1, cmap="mako")
sns.kdeplot(x=x, y=y, levels=5, color="w", linewidths=1)

logistic曲线绘制

logistic:调用logistic函数,需要import statsmodels

truncate:默认为True,改为False之后将不将曲线延长(比如这里红色的线,False的时候就后面那一节没有

image-20220913142407671

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import seaborn as sns
import statsmodels
sns.set_theme(style="darkgrid")

# Load the example Titanic dataset
df = sns.load_dataset("titanic")

# Make a custom palette with gendered colors
pal = dict(male="#6495ED", female="#F08080")

# Show the survival probability as a function of age and sex
g = sns.lmplot(x="age", y="survived", col="sex", hue="sex", data=df,
palette=pal, y_jitter=.02, logistic=True, truncate=False)
g.set(xlim=(0, 80), ylim=(-.05, 1.05))

步长图

image-20220913143823852

用到在学,感觉用不到Plotting on a large number of facets — seaborn 0.12.0 documentation (pydata.org)

半热力图

主要在于mask,将mask传入heatmap即可

image-20220913144508478

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from string import ascii_letters
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="white")

# Generate a large random dataset
rs = np.random.RandomState(33)
d = pd.DataFrame(data=rs.normal(size=(100, 26)),
columns=list(ascii_letters[26:]))

# Compute the correlation matrix
corr = d.corr()

# Generate a mask for the upper triangle
mask = np.triu(np.ones_like(corr, dtype=bool))

# Set up the matplotlib figure
f, ax = plt.subplots(figsize=(11, 9))

# Generate a custom diverging colormap
cmap = sns.diverging_palette(230, 20, as_cmap=True)

# Draw the heatmap with the mask and correct aspect ratio
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,
square=True, linewidths=.5, cbar_kws={"shrink": .5})

回归+分布图

同样是你最爱的jointplot()

image-20220913153241567

1
2
3
4
5
6
7
8
import seaborn as sns
sns.set_theme(style="darkgrid")

tips = sns.load_dataset("tips")
g = sns.jointplot(x="total_bill", y="tip", data=tips,
kind="reg", truncate=False,
xlim=(0, 60), ylim=(0, 12),
color="m", height=7)

残差图

image-20220913153518153

1
2
3
4
5
6
7
8
9
10
11
import numpy as np
import seaborn as sns
sns.set_theme(style="whitegrid")

# Make an example dataset with y ~ x
rs = np.random.RandomState(7)
x = rs.normal(2, 1, 75)
y = 2 + 1.5 * x + rs.normal(0, 2, 75)

# Plot the residuals after fitting a linear model
sns.residplot(x=x, y=y, lowess=True, color="g")

散点+分布图

他好像拿出了四个参数作为轴,同时画了四个图

image-20220913153617926

1
2
3
4
5
import seaborn as sns
sns.set_theme(style="ticks")

df = sns.load_dataset("penguins")
sns.pairplot(df, hue="species")

深邃热力+条形

image-20220913153827485

1
2
3
4
5
6
7
8
9
10
import seaborn as sns
sns.set_theme(style="white")

df = sns.load_dataset("penguins")

g = sns.JointGrid(data=df, x="body_mass_g", y="bill_depth_mm", space=0)
g.plot_joint(sns.kdeplot,
fill=True, clip=((2200, 6800), (10, 25)),
thresh=0, levels=100, cmap="rocket")
g.plot_marginals(sns.histplot, color="#03051A", alpha=1, bins=25)

带回归线的散点条形图

image-20220913154553697

1
2
3
4
5
6
7
8
9
10
11
12
import seaborn as sns
sns.set_theme()

mpg = sns.load_dataset("mpg")
sns.catplot(
data=mpg, x="cylinders", y="acceleration", hue="weight",
native_scale=True, zorder=1
)
sns.regplot(
data=mpg, x="cylinders", y="acceleration",
scatter=False, truncate=False, order=2, color=".2",
)

热力图+树状图

这个是指,多层索引传入,才可以画出来

image-20220913160340988

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import pandas as pd
import seaborn as sns
sns.set_theme()

# Load the brain networks example dataset
df = sns.load_dataset("brain_networks", header=[0, 1, 2], index_col=0)

# Select a subset of the networks
used_networks = [1, 5, 6, 7, 8, 12, 13, 17]
used_columns = (df.columns.get_level_values("network")
.astype(int)
.isin(used_networks))
df = df.loc[:, used_columns]

# Create a categorical palette to identify the networks
network_pal = sns.husl_palette(8, s=.45)
network_lut = dict(zip(map(str, used_networks), network_pal))

# Convert the palette to vectors that will be drawn on the side of the matrix
networks = df.columns.get_level_values("network")
network_colors = pd.Series(networks, index=df.columns).map(network_lut)

# Draw the full plot
g = sns.clustermap(df.corr(), center=0, cmap="vlag",
row_colors=network_colors, col_colors=network_colors,
dendrogram_ratio=(.1, .2),
cbar_pos=(.02, .32, .03, .2),
linewidths=.75, figsize=(12, 13))

g.ax_row_dendrogram.remove()

多重时间序列

image-20220913163645960

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import seaborn as sns

sns.set_theme(style="dark")
flights = sns.load_dataset("flights")

# Plot each year's time series in its own facet
g = sns.relplot(
data=flights,
x="month", y="passengers", col="year", hue="year",
kind="line", palette="crest", linewidth=4, zorder=5,
col_wrap=3, height=2, aspect=1.5, legend=False,
)

# Iterate over each subplot to customize further
for year, ax in g.axes_dict.items():

# Add the title as an annotation within the plot
ax.text(.8, .85, year, transform=ax.transAxes, fontweight="bold")

# Plot every year's time series in the background
sns.lineplot(
data=flights, x="month", y="passengers", units="year",
estimator=None, color=".7", linewidth=1, ax=ax,
)

# Reduce the frequency of the x axis ticks
ax.set_xticks(ax.get_xticks()[::2])

# Tweak the supporting aspects of the plot
g.set_titles("")
g.set_axis_labels("", "Passengers")
g.tight_layout()

丰富多彩的线图

image-20220913163818729

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
import pandas as pd
import seaborn as sns
sns.set_theme(style="whitegrid")

rs = np.random.RandomState(365)
# cumsum axis=0时,返回行的累计和,也就是第二行变成了原本的第二行+第一行的值
# randn(365, 4)返回的是365 * 4的一个numpy的n维数组
values = rs.randn(365, 4).cumsum(axis=0)
dates = pd.date_range("1 1 2016", periods=365, freq="D")
data = pd.DataFrame(values, dates, columns=["A", "B", "C", "D"])
data = data.rolling(7).mean()
sns.lineplot(data=data, palette="tab10", linewidth=2.5)

生成Mp4,gif

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""
一图胜千言
动图胜万言
python 生成
gif, mp4
"""
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np

fig, ax = plt.subplots()
xdata = []
ydata = []

line, = plt.plot(xdata, ydata, 'r-')


def init():
# 定轴
ax.set_xlim(-1, 6)
ax.set_ylim(-1, 30)
# 返回的是一个子图,由于subplot没有指定大小,所以最终就只显示一个图吧
return line,


def update(frame): # 帧
print(frame)
xdata.append(frame)
ydata.append(frame ** 2)

line.set_data(xdata, ydata)
return line,


ani = animation.FuncAnimation(
# 表示是在那个轴的基础上干的
fig=fig,
# func就是每一帧该干的事
func=update,
# frames=[1, 2, 3],
# 0 - 5线性插值作为基础数据,画均匀增大的直线
frames=np.linspace(0, 5, 100),
# frames=5,
# 初始化函数
init_func=init,
# 每隔多长时间生成一张动图
# 用间隔乘以帧(点数)来
interval=100, # 时间间隔: 毫秒
# 是否重复播放
repeat=False
)
# plt.show()
# gif和mp4每次只生成一个
ani.save('1.gif', writer='pillow')
# ani.save('1.mp4')

多图同屏版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np

fig, ax = plt.subplots()

# 固定的线
plt.plot([1, 2], [10, 20], 'b-')

# 线1
xdata = []
ydata = []
line, = plt.plot(xdata, ydata, 'r-')
# 线2
xdata2 = []
ydata2 = []
line2, = plt.plot(xdata2, ydata2, 'g-')

# 文字
x_template = 'x = %.2f'
# 0.05,0.9即占xy图的位置比例,这个也就是左上角
x_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)


def init():
ax.set_xlim(-1, 6)
ax.set_ylim(-1, 30)
return line, line2, x_text


def update(frame, n): # 帧
print(frame)
# 线1
xdata.append(frame)
ydata.append(frame ** 2)
line.set_data(xdata, ydata)
# 线2
xdata2.append(frame)
ydata2.append(frame ** n)
line2.set_data(xdata2, ydata2)

# 文字
x_text.set_text(x_template % frame)
return line, line2, x_text


ani = animation.FuncAnimation(
fig=fig,
func=update,
# frames=[1, 2, 3],
frames=np.linspace(0, 5, 100),
# frames=5,
init_func=init,
interval=100, # 时间间隔: 毫秒
repeat=False,
# blit参数,默认为False,即每次画图都将之前的删除重画,为True时代表不删除。
blit=True,
# fargs需要传入元祖,是用来传入update的参数, 例如这样就是传入update一个固定参数,还可以逗号后再传参数
# 总之就是可以传入多个参数
fargs=(4,)
)
plt.show()
# ani.save('1.gif', writer='pillow')
# ani.save('1.mp4')

实战

主要步骤

合并单平台表

image-20220921113506268

JD TB双平台 + 各种咋二八斤的表合并

image-20220921113629745

image-20220921113909838

得出信息

image-20220921114000698

这里只给出我看到的一些,值得注意的细节:

image-20220921115055525

,将退货数量为0的列,设置其退货金额为0