Pandas的来历
Pandas是Python生态系统中最强大的数据分析工具,其提供了高性能、易用的数据结构和数据分析方法,它由Wes McKinney于2008年开始开发,最初是为了满足金融数据分析的需求,后来常常用于机器学习中的数据处理,我现在要学习机器学习,所以写下这一个笔记,方便我日后使用。
Pandas的代码建立在NumPy库的基础上,使用Numpy数组作为其数据结构的基础,但相比使用Numpy,Pandas提供了更多高级的功能。我个人认为Pandas是可以视作Numpy的一种高级扩展。写相关的Python代码时候一般需要两个一起导入在头文件导入。
Pandas的核心数据结构
Pandas中的Series结构
首先是Series,Series是Pandas的基础的数据结构之一,它是一个带有标签的一维数组,可以用Series来储存任何的数据类型(比如说整数、浮点数等各种数,还有不同的Python数组之类的,甚至可以储存Python对象),我觉得可以将其看成一个类似字典的对象,在这个Series结构中,每个内容都有对应的索引(Index)以及其对应的值(Values)
那么,我们先了解下Series的创建方法。
我们先用一个简单的代码来做例子,比如下面的代码
import numpy as np # 添加这一行导入NumPy
import pandas as pd
s1 = pd.Series([1,2,3,4,5]) #从列表中创建
print(s1)
s2 = pd.Series([1,2,3,4,[123,321,1234567],np.nan])#可以往创建列表中加入些其他的东西
print(s2)
s3 = pd.Series(np.array([1, 2, 3, 0, 6])) #当然也可以从numpy数组中进行创建
print(s3)
上面的代码运行结果是
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
0 1
1 2
2 3
3 4
4 5
dtype: int64
0 1
1 2
2 3
3 4
4 [123, 321, 1234567]
5 NaN
dtype: object
0 1
1 2
2 3
3 0
4 6
dtype: int64
进程已结束,退出代码为 0
上面的例子介绍了下2种创建series结构的方法,第一种是直接从一个python列表进行创建,并且我在其中还展示了,列表中可以加入些其他的东西,比如数组或者是python对象,第二种则是直接通过NUMPY的数组来进行创建
Pandas中的DataFrame结构
DataFrame在Pandas中,相比Series,使用更多,更广泛。它是一个二维的表格形的数据结构,由行与列组成,很像我们平常使用的Excel表格,同时拥有行索引和列索引,我认为其可以看做是多个共享同一个索引的Series集合,内置了大量的数据分析和数据处理的操作
那么我们来介绍下DataFrame如何进行创建。
我们仍然以简单的代码来做例子:
import numpy as np # 添加这一行导入NumPy
import pandas as pd
#嘻嘻,下面是本站的一部分友情链接,所以我用友情链接的数据来创建一个DataFrame来做介绍
data = {'Name': ['q2019', '花开陌上', '南蛮子懋和', 'Zerun-s BLOG'],
'Website': ['q2019.com', 'moshanghua.net', 'www.dao.js.cn', 'blog.zeruns.com'],
'introduce': ['乐天派一枚', '待我熬尽一日苦,喂你一口甜。', '李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。', '爱折腾软件和硬件的技术宅']}#这是一个字典类型
df = pd.DataFrame(data)#从字典类型中创建了一个DataFrame
print("下面是使用字典类型创建的")
print(df)
data = [
['q2019', 'q2019.com', '乐天派一枚'],
['花开陌上', 'moshanghua.net', '待我熬尽一日苦,喂你一口甜。'],
['南蛮子懋和', 'www.dao.js.cn', '李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。'],
['Zerun-s BLOG', 'blog.zeruns.com', '爱折腾软件和硬件的技术宅']
] #这是一个数组类型
# df_2 = pd.DataFrame(data) #从数组中创建了一个DataFrame,注释掉的的是不带表头的
df_2 = pd.DataFrame(data, columns=['Name', 'Website', 'Introduce'])#这个样子可以让dataframe带一个表头
print("下面是使用数组类型创建的")
print(df_2)
data = np.array([['q2019', 'q2019.com', '乐天派一枚'],
['花开陌上', 'moshanghua.net', '待我熬尽一日苦,喂你一口甜。'],
['南蛮子懋和', 'www.dao.js.cn', '李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。'],
['Zerun-s BLOG', 'blog.zeruns.com', '爱折腾软件和硬件的技术宅']]) #这是一个NumPy数组
df_3 = pd.DataFrame(data) #从NumPy数组中创建的一个DataFrame,这里我就不带表头了
#df_3 = pd.DataFrame(data, columns=['Name', 'Website', 'Introduce']) 这一行注释掉的是带了表头的
print("下面是numpy数组类型创建的")
print(df_3)
name = pd.Series(['q2019', '花开陌上', '南蛮子懋和', 'Zerun-s BLOG'])#这个是一个Series
website = pd.Series(['q2019.com', 'moshanghua.net', 'www.dao.js.cn/', 'blog.zeruns.com/'])#这个是一个Series
introduce = pd.Series(['乐天派一枚', '待我熬尽一日苦,喂你一口甜。', '李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。', '爱折腾软件和硬件的技术宅'])#这个是一个Series
df_4 = pd.DataFrame({'Name': name, 'Website': website, 'Introduce': introduce})
print("下面是Series数组类型创建的")
print(df_4)
上面的运行结果如下:
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
下面是使用字典类型创建的
Name Website introduce
0 q2019 q2019.com 乐天派一枚
1 花开陌上 moshanghua.net 待我熬尽一日苦,喂你一口甜。
2 南蛮子懋和 www.dao.js.cn 李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。
3 Zerun-s BLOG blog.zeruns.com 爱折腾软件和硬件的技术宅
下面是使用数组类型创建的
Name Website Introduce
0 q2019 q2019.com 乐天派一枚
1 花开陌上 moshanghua.net 待我熬尽一日苦,喂你一口甜。
2 南蛮子懋和 www.dao.js.cn 李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。
3 Zerun-s BLOG blog.zeruns.com 爱折腾软件和硬件的技术宅
下面是numpy数组类型创建的
0 1 2
0 q2019 q2019.com 乐天派一枚
1 花开陌上 moshanghua.net 待我熬尽一日苦,喂你一口甜。
2 南蛮子懋和 www.dao.js.cn 李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。
3 Zerun-s BLOG blog.zeruns.com 爱折腾软件和硬件的技术宅
下面是Series数组类型创建的
Name Website Introduce
0 q2019 q2019.com 乐天派一枚
1 花开陌上 moshanghua.net 待我熬尽一日苦,喂你一口甜。
2 南蛮子懋和 www.dao.js.cn/ 李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。
3 Zerun-s BLOG blog.zeruns.com/ 爱折腾软件和硬件的技术宅
进程已结束,退出代码为 0
上面的代码使用了四种方法来创建,分别为使用字典类型,数组类型,Numpy数组类型以及Series类型(这个也证明了DataFrame可以看做是多个共享同一个索引的Series集合)
(有个需要注意的点,就是DataFrame是有一个列名和行名的,默认情况下使用字典类型和Series会有列名,但是使用数组是没有的,但是可以手动创建)
数据集导入以及数据集导出
既然知道了Pandas的基本的数据结构,那么我们就要开始往里头加数据了
我们用下面的数据集做个例子,这个数据集是泰坦尼克号数据集,是基于1912年4月泰坦尼克号沉船事故中真实的乘客数据采集而来,我找到的数据集已经分为了两个,在这篇文章中我们随便选择一个文件下载就行了
备用下载地址:https://wwhq.lanzouu.com/irNeO2u0jd7c
导入
我们下面以导入CSV文件为例子
import numpy as np # 添加这一行导入NumPy
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
print(TitanicData.head())
上述代码导入了我刚刚提供的 TitanicTrain.csv文件,并显示其中的几行,结果如下
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
[5 rows x 12 columns]
进程已结束,退出代码为 0
当然了,不仅仅是导入csv文件,Pandas也可以导入很多其他的文件,比如说SqlLite文件、json文件和html文件,下面是示例代码
# 需要先安装 openpyxl 库
titanic_excel = pd.read_excel('titanic.xlsx', sheet_name='Sheet1')
# 导入JSON文件
titanic_json = pd.read_json('titanic.json')
#从SQLITE导入
import sqlite3
conn = sqlite3.connect('database.db')
titanic_sql = pd.read_sql('SELECT * FROM titanic', conn)
这个导入进来,Pandas会将这些文件储存为刚刚所说的一个DataFrame。
导出
当然,有导入肯定有导出,不可能只进不出,Pandas能够将导入的数据集导出为不同的格式,但是我们也就只记录下如何导出为CSV文件和JSON文件。下面是导出的代码
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
TitanicData.to_csv('Export_1.csv')#导出为CSV文件
TitanicData.to_csv('Export_2.csv',index=False,sep=',')#导出为CSV文件,但是不包含索引,指定每个数据的分割符号为“,“
TitanicData.to_json('Export_1.json')#导出为Json文件
TitanicData.to_json('Export_2.json', orient='records')#导出为JSON,但是指定了导出选项为"records",与之相对的还有默认的"columns","index",个人感觉使用records清楚些
输出四个文件,因为输出结果较大,我就只取一部分:
Export_1.csv:
,PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
0,1,0,3,"Braund, Mr. Owen Harris",male,22.0,1,0,A/5 21171,7.25,,S
1,2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38.0,1,0,PC 17599,71.2833,C85,C
2,3,1,3,"Heikkinen, Miss. Laina",female,26.0,0,0,STON/O2. 3101282,7.925,,S
3,4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35.0,1,0,113803,53.1,C123,S
Export_2.csv:
PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
1,0,3,"Braund, Mr. Owen Harris",male,22.0,1,0,A/5 21171,7.25,,S
2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38.0,1,0,PC 17599,71.2833,C85,C
3,1,3,"Heikkinen, Miss. Laina",female,26.0,0,0,STON/O2. 3101282,7.925,,S
4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35.0,1,0,113803,53.1,C123,S
Export_1.json(不全)
{"PassengerId":{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"6":7,"7":8,"8":9,"9":10,"10":11,"11":12,"12":13,"13":14,"14":15,"15":16,"16":17,"17":18,"18":19,"19":20,"20":21,"21":22,"22":23,"23":24,"24":25,"25":26,"26":27,"27":28,"28":29,"29":30,"30":31,"31":32,"32":33,"33":34,"34":35,"35":36,"36":37,"37":38,"38":39,"39":40,"40":41,"41":42,"42":43,"43":44,"44":45,"45":46,"46":47,"47":48,"48":49,"49":50,"50":51,"51":52,"52":53,"53":54,"54":55,"55":56,"56":57,"57":58,"58":59,"59":60,"60":61,"61":62,"62":63,"63":64,"64":65,"65":66,"66":67,"67":68,"68":69,"69":70,"70":71,"71":72,"72":73,"73":74,"74":75,"75":76,"76":77,"77":78,"78":79,"79":80,"80":81,"81":82,"82":83,"83":84,"84":85,"85":86,"86":87,"87":88,"88":89,"89":90,"90":91,"91":92,"92":93,"93":94,"94":95,"95":96,"96":97,"97":98,"98":99,"99":100,"100":101,"101":102,"102":103,"103":104,"104":105,"105":106,"106":107,"107":108,"108":109,"109":110,"110":111,"111":112,"112":113,"113":114,"114":115,"115":116,"116":117,"117":118,"118":119,"119":1
Export_2.json
[{"PassengerId":1,"Survived":0,"Pclass":3,"Name":"Braund, Mr. Owen Harris","Sex":"male","Age":22.0,"SibSp":1,"Parch":0,"Ticket":"A\/5 21171","Fare":7.25,"Cabin":null,"Embarked":"S"},{"PassengerId":2,"Survived":1,"Pclass":1,"Name":"Cumings, Mrs. John Bradley (Florence Briggs Thayer)","Sex":"female","Age":38.0,"SibSp":1,"Parch":0,"Ticket":"PC 17599","Fare":71.2833,"Cabin":"C85","Embarked":"C"},{"PassengerId":3,"Survived":1,"Pclass":3,"Name":"Heikkinen, Miss. Laina","Sex":"female","Age":26.0,"SibSp":0,"Parch":0,"Ticket":"STON\/O2. 3101282","Fare":7.925,"Cabin":null,"Embarked":"S"},{"PassengerId":4,"Survived":1,"Pclass":1,"Name":"Futrelle, Mrs. Jacques Heath (Lily May Peel)","Sex":"female","Age":35.0,"SibSp":1,"Parch":0,"Ticket":"113803","Fare":53.1,"Cabin":"C123","Embarked":"S"},{"PassengerId":5,"Survived":0,"Pclass":3,"Name":"Allen, Mr. William Henry","Sex":"male","Age":35.0,"SibSp":0,"Parch":0,"Ticket":"373450","Fare":8.05,"Cabin":null,"Embarked":"S"},{"PassengerId":6,
上面的内容有所截断,但是也可以看出各个导出文件方法的效果的不同。注意下,Pandas的导出默认是覆盖之前的文件的导出方法。
数据查看
导入了数据,我们就要来进行数据的查看了。
基本行数据查看
下面是示例代码
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
print(TitanicData.head())#查看前5行数据(默认为5行)
print(TitanicData.head(3))#查看前3行的数据
print(TitanicData.tail())#查看后5行数据(默认为5行)
print(TitanicData.tail(3))#查看最后5行的数据
print(TitanicData.sample(3))#随机抽选3个样例数据
结果如下:
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
[5 rows x 12 columns]
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
[3 rows x 12 columns]
PassengerId Survived Pclass ... Fare Cabin Embarked
886 887 0 2 ... 13.00 NaN S
887 888 1 1 ... 30.00 B42 S
888 889 0 3 ... 23.45 NaN S
889 890 1 1 ... 30.00 C148 C
890 891 0 3 ... 7.75 NaN Q
[5 rows x 12 columns]
PassengerId Survived Pclass ... Fare Cabin Embarked
888 889 0 3 ... 23.45 NaN S
889 890 1 1 ... 30.00 C148 C
890 891 0 3 ... 7.75 NaN Q
[3 rows x 12 columns]
PassengerId Survived Pclass ... Fare Cabin Embarked
705 706 0 2 ... 26.0000 NaN S
702 703 0 3 ... 14.4542 NaN C
9 10 1 2 ... 30.0708 NaN C
[3 rows x 12 columns]
DataFrame相关属性信息查看
下面是示例代码
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
print(TitanicData.info()) #查看这个DataFrame的基本的信息)
print(TitanicData.describe()) #查看这个DataFrame的数值列的统计摘要信息
print(TitanicData.describe(include=['object', 'category'])) #查看DataFrame的非数值列的统计摘要
print(TitanicData.shape) #查看DataFrame的行数和列数
print(TitanicData.columns) #查看所有的列名(列索引)
print(TitanicData.index) #查看所有的行名(行索引)
print(TitanicData.dtypes) #查看数据类型
运行结果如下:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None
PassengerId Survived Pclass ... SibSp Parch Fare
count 891.000000 891.000000 891.000000 ... 891.000000 891.000000 891.000000
mean 446.000000 0.383838 2.308642 ... 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 ... 1.102743 0.806057 49.693429
min 1.000000 0.000000 1.000000 ... 0.000000 0.000000 0.000000
25% 223.500000 0.000000 2.000000 ... 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 ... 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 ... 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 ... 8.000000 6.000000 512.329200
[8 rows x 7 columns]
Name Sex Ticket Cabin Embarked
count 891 891 891 204 889
unique 891 2 681 147 3
top Dooley, Mr. Patrick male 347082 G6 S
freq 1 577 7 4 644
(891, 12)
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
dtype='object')
RangeIndex(start=0, stop=891, step=1)
PassengerId int64
Survived int64
Pclass int64
Name object
Sex object
Age float64
SibSp int64
Parch int64
Ticket object
Fare float64
Cabin object
Embarked object
dtype: object
上面代码中的注释已经很好的解释了每行的意义。
特定数据信息查看
查看了宏观的数据,那么我们也要查看特定的数据,如下面的例子
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
print(TitanicData["PassengerId"].head())#查看列"passengerID"这个的数据,直接索引列数据
print(TitanicData[0:5])#当然也可以整数切片选择行
运行结果如下
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
0 1
1 2
2 3
3 4
4 5
Name: PassengerId, dtype: int64
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
[5 rows x 12 columns]
进程已结束,退出代码为 0
这例是通过直接索引来选择行列中的数据,但是这个样子感觉非常的不灵活,难不成没有一个更好的方法吗?肯定是有的,接下来就是数据的选择和索引了
数据选择和索引
上面的简单的数据查看方法肯定是不够我们平常使用的,太不灵活和方便了,所以Pandas提供了非常丰富的数据选择与过滤以及索引的方法。那么首先就是讲解下索引
索引的基本概念
在Pnadas中,索引是DataFrame和Series对象的一个比较特殊的组件,其为每一行(或者每个元素)提供了标签
我们主要来讲DataFrame数据结构的索引
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
print(TitanicData.index)#这个是行索引
print(TitanicData.columns)#这个是列索引
下面是输出的结果
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
RangeIndex(start=0, stop=891, step=1)
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
dtype='object')
进程已结束,退出代码为 0
索引分两种,行索引和列索引,行索引是指明每一行的,列索引是指明每一列的
当我们创建一个DataFrame时候,如果没有指定索引,Pandas会自动创建一个默认的行索引(通常是一个从0开始的整数序列),而列索引则一般是表头的信息。
当然,我们可以不让Pandas自动设置索引,而是我们自己设定索引,比如说下面的代码,我们将DataFrame的索引设置为Name,代码如下
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
TitanicData.set_index('Name', inplace=True)
print(TitanicData.head())
结果如下。
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
PassengerId ... Embarked
Name ...
Braund, Mr. Owen Harris 1 ... S
Cumings, Mrs. John Bradley (Florence Briggs Tha... 2 ... C
Heikkinen, Miss. Laina 3 ... S
Futrelle, Mrs. Jacques Heath (Lily May Peel) 4 ... S
Allen, Mr. William Henry 5 ... S
[5 rows x 11 columns]
进程已结束,退出代码为 0
可以看到,相比原来的默认索引,我们这边输出的内容一开始就是以用户名来进行输出的。我这边是使用的行索引,列索引相关的则改为使用set_columns,其余不谈。还有要注意的一点就是,当你设置索引之后,设置索引的列不再是普通的数据列了,而是成为了索引的一部分,无法作为普通列被访问了
当然这里要提一嘴,默认使用set_index 之类的是不会再原有的DataFrame上进行修改,而是函数执行完后返回一个DataFrame对象,除非参数中有inplace=True ,这样才会在原有DataFrame上进行修改
多级索引
当然,索引只能有一个吗?肯定不可能,可以在一个数据集中设置好几个索引(也称之为多级索引),如下面的代码
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
TitanicData.set_index(['Name','Embarked'], inplace=True)
print(TitanicData.head(10))
运行结果:
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
PassengerId ... Cabin
Name Embarked ...
Braund, Mr. Owen Harris S 1 ... NaN
Cumings, Mrs. John Bradley (Florence Briggs Tha... C 2 ... C85
Heikkinen, Miss. Laina S 3 ... NaN
Futrelle, Mrs. Jacques Heath (Lily May Peel) S 4 ... C123
Allen, Mr. William Henry S 5 ... NaN
Moran, Mr. James Q 6 ... NaN
McCarthy, Mr. Timothy J S 7 ... E46
Palsson, Master. Gosta Leonard S 8 ... NaN
Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg) S 9 ... NaN
Nasser, Mrs. Nicholas (Adele Achem) C 10 ... NaN
[10 rows x 10 columns]
进程已结束,退出代码为 0
其设置了多级索引Name 和Embarked,所以在下面的head()输出最左边显示Name,其次是Embarked.
通过索引进行标签访问
进行了索引,那么我们也就要进行访问,Pandas中访问数据有两种,基于标签的访问(.loc[])和基于位置的访问(.iloc[])
首先介绍下基于标签的访问,也是直接上例子
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
TitanicData.set_index(['PassengerId','Sex'], inplace=True)#设置PassengerId以及Sex为索引
#访问特定的行
print(TitanicData.loc[1])#找到Id为1的那位并输出出来
print(TitanicData.loc[[1,3,5]])#找3个人,但是都用Id来查找
print(TitanicData.loc[1:5])#找到Id为1-5的几个人,这个也叫做切片访问,但是请注意,这个是包含最后一个数据的
print(TitanicData.loc[1])#找3个人,但是都用Id来查找
#访问特定的列
print(TitanicData.loc[:,'Name'])#这个代表的含义是“:”所有行,“Name",名为Name的列
#行列组合访问
print(TitanicData.loc[1:5,['Name','Embarked']])
运行结果
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
Survived Pclass Name ... Fare Cabin Embarked
Sex ...
male 0 3 Braund, Mr. Owen Harris ... 7.25 NaN S
[1 rows x 10 columns]
Survived Pclass ... Cabin Embarked
PassengerId Sex ...
1 male 0 3 ... NaN S
3 female 1 3 ... NaN S
5 male 0 3 ... NaN S
[3 rows x 10 columns]
Survived Pclass ... Cabin Embarked
PassengerId Sex ...
1 male 0 3 ... NaN S
2 female 1 1 ... C85 C
3 female 1 3 ... NaN S
4 female 1 1 ... C123 S
5 male 0 3 ... NaN S
[5 rows x 10 columns]
Survived Pclass Name ... Fare Cabin Embarked
Sex ...
male 0 3 Braund, Mr. Owen Harris ... 7.25 NaN S
[1 rows x 10 columns]
PassengerId Sex
1 male Braund, Mr. Owen Harris
2 female Cumings, Mrs. John Bradley (Florence Briggs Th...
3 female Heikkinen, Miss. Laina
4 female Futrelle, Mrs. Jacques Heath (Lily May Peel)
5 male Allen, Mr. William Henry
...
887 male Montvila, Rev. Juozas
888 female Graham, Miss. Margaret Edith
889 female Johnston, Miss. Catherine Helen "Carrie"
890 male Behr, Mr. Karl Howell
891 male Dooley, Mr. Patrick
Name: Name, Length: 891, dtype: object
Name Embarked
PassengerId Sex
1 male Braund, Mr. Owen Harris S
2 female Cumings, Mrs. John Bradley (Florence Briggs Th... C
3 female Heikkinen, Miss. Laina S
4 female Futrelle, Mrs. Jacques Heath (Lily May Peel) S
5 male Allen, Mr. William Henry S
进程已结束,退出代码为 0
首先就是要来介绍关于这个的参数,loc的参数如下:
DataFrame.loc[row_indexer, column_indexer]
其中row_indexer是行索引器,colunm_indexer是列索引器。通过这两个参数索引出我们需要的数据。如果只有一个的话默认是行索引器(就如我给的例子中的TitanicData.loc[1]),填入对应的参数,进行选择
当然,可以做到的远远不止于此,这个还能进行条件选择,下面是条件选择的示例代码
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
TitanicData.set_index(['PassengerId'], inplace=True)#设置PassengerId以及Sex为索引
#访问特定的行
print(TitanicData.loc[(TitanicData['Age'] > 30) & (TitanicData['Survived'] == 1),'Name'])#找到年龄大于30并且还存活的人的名字
输出如下
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
PassengerId
2 Cumings, Mrs. John Bradley (Florence Briggs Th...
4 Futrelle, Mrs. Jacques Heath (Lily May Peel)
12 Bonnell, Miss. Elizabeth
16 Hewlett, Mrs. (Mary D Kingcome)
22 Beesley, Mr. Lawrence
...
858 Daly, Mr. Peter Denis
863 Swift, Mrs. Frederick Joel (Margaret Welles Ba...
866 Bystrom, Mrs. (Karolina)
872 Beckwith, Mrs. Richard Leonard (Sallie Monypeny)
880 Potter, Mrs. Thomas Jr (Lily Alexenia Wilson)
Name: Name, Length: 124, dtype: object
进程已结束,退出代码为 0
讲完了这个,还有一个iloc[],参数还是如下
DataFrame.iloc[row_indexer, column_indexer]
loc是通过标签来进行选择,而iloc则是基于位置来进行选择的,其余大致都与loc相等,还是看代码
import pandas as pd
TitanicData = pd.read_csv('TitanicTrain.csv')
TitanicData.set_index(['PassengerId'], inplace=True)#设置PassengerId以及Sex为索引
#访问特定的行
print(TitanicData.iloc[1])#第一行
print(TitanicData.iloc[1:7,3:5])#1-7行的每行3-5列
结果如下
C:\Users\q2019\PycharmProjects\python_study\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\python_study\main.py
Survived 1
Pclass 1
Name Cumings, Mrs. John Bradley (Florence Briggs Th...
Sex female
Age 38.0
SibSp 1
Parch 0
Ticket PC 17599
Fare 71.2833
Cabin C85
Embarked C
Name: 2, dtype: object
Sex Age
PassengerId
2 female 38.0
3 female 26.0
4 female 35.0
5 male 35.0
6 male NaN
7 male 54.0
进程已结束,退出代码为 0
当然,这个不仅可以做到数据查询,也可以做到数据修改,下面给一张对比表吧
特性 | .loc[] | .iloc[] |
---|---|---|
索引类型 | 基于标签 | 基于位置(整数) |
切片特性 | 包含结束标签 | 不包含结束位置 |
使用场景 | 知道确切的索引标签时 | 需要按位置访问或不关心具体标签时 |
多级索引 | 可以使用元组访问各级 | 只能使用整数位置 |
缺失值处理
对于获取到的数据,我们是无法保证获取到的数据是完整的。数据集中尝尝会有缺失的值。所以我们需要对其中的缺失值进行处理。一般情况下是对缺失值进行丢弃或者取众数、中位数等。不说废话,还是直接上代码。
import pandas
import pandas as pd
Data = pandas.read_csv("TitanicTrain.csv")
print(Data.isnull().sum())
Data['Age'].fillna(Data['Age'].mean(), inplace=True) #使用均值来进行填充
Data['Embarked'].fillna(Data['Embarked'].mode()[0], inplace=True)#使用众数来进行填充
Data.dropna(inplace=True) #删除所有带有Na的行
print(Data.isnull().sum())
上面的代码对Data这个对象中的空值通过fillna这个函数进行了填充,其中第一个参数代表了要填充为什么,第二个参数“inplace = True”,代表了在原始的对象上进行修改,运行结果如下
C:\Users\q2019\PycharmProjects\PythonProject\.venv\Scripts\python.exe C:\Users\q2019\PycharmProjects\PythonProject\main.py
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 0
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 0
Embarked 0
dtype: int64
C:\Users\q2019\PycharmProjects\PythonProject\main.py:5: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.
For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.
Data['Age'].fillna(Data['Age'].mean(), inplace=True) #使用均值来进行填充
C:\Users\q2019\PycharmProjects\PythonProject\main.py:6: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.
For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.
Data['Embarked'].fillna(Data['Embarked'].mode()[0], inplace=True)#使用众数来进行填充
可以看到缺失的值全部没有了
这里有一个小问题:出现了两个警告“FutureWarning”,这是因为在后面版本的Pandas (Pandas3.0)之后, inplace=True这个参数可能就不会生效了(即不会进行替换),到时候我们可以通过创建一个新的对象,比如使用NewData=Data[‘Age’].fillna(Data[‘Age’].mean()) 这样来进行替换。
异常数据清理
异常数据清理
在拿到数据之后,有一些数据是有失真或者是错误的,但是这些的数据的错误可能会干扰后续的模型。所以我们最好还是提前将这些错误的数据给“清理”掉,刚好,Pandas能够实现数据清理的功能。下面就是清理的方法。
import pandas
Data = pandas.read_csv("TitanicTrain.csv")
Data = Data[Data['Age'] <= 100]#这样就进行替换了
可以看到进行替换的代码非常简单,只需要进行简单的筛选,然后将筛选后的重新赋值给自己,就完成了数据的清理,比如我上面的代码就是删除掉了年龄大于100的数值。
当然有时候我们无法凭借常理来判断哪些数据是有问题的,也可以使用标准差法等来判断异常数据
特征转化以及编码
特征转化的概念
什么是特征转化?这可能一开始让人听起来摸不起头脑,特征转化是指将原始数据中的特征,通过一系列的算法变成另外一种形式,让数据更好的用于机器学习。不仅可以避免极端的值对模型进行了过大的干扰,提升鲁棒性。对于数据分布比较敏感的模型,也能很好的提升模型的性能。一句话来说,特征转化就是“加工原始数据特征,提高数据质量”
数据的归一化
比较常见的数据转化就有归一化。归一化是将许多特征的数值全部归一到同一个范围,让各个特征在同一个范围进行数据的处理。这样子可以避免一个特征过多的在一个模型中占据主导权。
还是泰坦尼克号数据集作为例子,先给公式
$$x’ = \frac{x – x_{\text{min}}}{x_{\text{max}} – x_{\text{min}}}$$
其中:
- $( x )$:原始特征值
- $( x_{\text{min}} )$:该列最小值
- $( x_{\text{max}} )$:该列最大值
- $( x’ )$:归一化后的特征
知道原理,来使用Pandas进行下归一(其实一般是使用sklearn来进行归一的,但是Pandas也能做)
import pandas as pd
Data = pd.read_csv("TitanicTrain.csv")
num_cols = Data.select_dtypes(include=['number']).columns# 选取数值类型的值
for col in num_cols:
min_col = Data[col].min()
max_col = Data[col].max()
Data[col + '_norm'] = (Data[col] - min_col) / (max_col - min_col)#按照刚刚的公式进行归一
print(Data[[col + '_norm' for col in num_cols]].head())#查看下数据
接下来结果如下,可以看到大部分的值都在0-1之间了
PassengerId_norm Survived_norm ... Parch_norm Fare_norm
0 0.000000 0.0 ... 0.0 0.014151
1 0.001124 1.0 ... 0.0 0.139136
2 0.002247 1.0 ... 0.0 0.015469
3 0.003371 1.0 ... 0.0 0.103644
4 0.004494 0.0 ... 0.0 0.015713
当然,因为本文主要是用来介绍Pandas的,而不是介绍数据的归一的。所以也就先介绍这么多,对数变化,分箱之类的,有兴趣的话我再别的博文中再说
数据透视以及数据重塑
数据透视在Pandas中就是一种能够让我们快速进行数据处理以及分析的方法。它能够按照一个或多个字段(维度)对原始数据进行“分组”“统计”“聚合”,快速地生成交叉汇总表或多维报表,然后让我们进行查看(即“透视”)
数据聚合则是指将分散的明细数据,根据某种规则,通过某些统计方法合并成更简明、汇总性的数据,说人话其实就是数据汇总。下面是代码
import pandas as pd
Data = pd.read_csv("TitanicTrain.csv")
pivot1 = pd.pivot_table(Data,
index='Pclass', # 行分组:船舱等级
columns='Sex', # 列分组:性别
values='Survived', # 要统计的字段
aggfunc='sum') # 聚合方式:求和(即幸存人数)
print(pivot1)
运行结果如下
Sex female male
Pclass
1 91 45
2 70 17
3 72 47
后记
这只是一篇粗略的笔记,可能有所不足,甚至可能有错误,我到时候也会不断地进行更新的