关于Python的Pandas库

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
加载Katex数学渲染引擎中…
30%
恭喜!KATEX数学渲染引擎已加载完成

后记

这只是一篇粗略的笔记,可能有所不足,甚至可能有错误,我到时候也会不断地进行更新的

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,记得载明出处。
内容有问题?想与我交流下?点此哦,欢迎前来交流~
上一篇