数据、Series对象、DataFrame对象、绝对路径和相对路径、多个html表格的拼接及排序、loc与iloc的区别、数据的增修改和删除、数据清洗、异常值)"/>
pandas统计分析上(导入excel数据、Series对象、DataFrame对象、绝对路径和相对路径、多个html表格的拼接及排序、loc与iloc的区别、数据的增修改和删除、数据清洗、异常值)
- 本篇博客内容来自《Python数据分析从入门到精通》_明日科技编著
3.1 pandas
3.1.3 导入Excel数据
import pandas as pd #导入pandas模块
#解决数据输出时列名不对齐的问题,在jup中无需下面这行代码
#pd.set_option('display.unicode.east_asian_width', True)
df=pd.read_excel('data.xlsx') #读取Excel文件
df.head() #在jup中如果使用print函数打印结果会出现列名不对齐的情况
3.2 Series对象
- Pandas是Python数据分析重要的库,而Series和DataFrame是Pandas库中两个重要的对象,也是Pandas中两个重要的数据结构,如下图所示。
维数 | 名称 | 描述 |
---|---|---|
1 | Series | 带标签的一维同构数组 |
2 | DataFrame | 带标签的,大小可变的,二维异构的表格 |
3.2.1 图解Series对象
- Series是Python的Pandas库中的一种数据结构,它类似一维数组,由一组数据以及与这组数据相关的标签(即索引)组成,或者仅有一组数据没有索引也可以创建一个简单的Series。Series可以存储整数、浮点数、字符串、Python对象等多种类型的数据。
- 例如,在成绩表中包含了Series对象,其中“语文”“数学”“英语”3列中的每一列均是一个Series对象,而“语文”“数学”“英语”3列组成了一个DataFrame对象,如下图:
语文 | 数学 | 英语 | |
---|---|---|---|
0 | 110 | 105 | 99 |
1 | 105 | 88 | 115 |
2 | 109 | 120 | 130 |
3.2.2 创建一个Series对象
- 创建Series对象主要使用Pandas的Series()方法,语法如下:
s = pd.Series(data,index=index)
- 参数说明:
– data:表示数据,支持Python字典、多维数组、标量值(即只有大小,没有方向的量)。也就是说,只是一个数值,如s=pd.Series(5)。
– index:表示行标签(索引)
– 返回值:Series对象
当data参数是多维数组时,index长度必须与data长度一致。如果没有指定index参数,则自动创建数值型索引(从0~data数据长度-1)。
- 创建一个Series对象,在成绩表中添加一列“物理”成绩。程序代码如下:
import pandas as pd
s1=pd.Series([88,60,75])
s1
3.2.3 手动设置Series索引
- 创建Series对象时会自动生成整数索引,默认值从0开始至数据长度减1。例如3.2.1节举例中使用的就是默认索引,如0、1、2。除了使用默认索引,还可以通过index参数手动设置索引。
- 手动设置索引,将3.2.1节添加的“物理”成绩的索引设置为1、2、3,也可以是“明日同学”“高同学”“七月流火”。程序代码如下:
import pandas as pd
s1=pd.Series([88,60,75],index=[1,2,3])
s2=pd.Series([88,60,75],index=['明日同学','高同学','七月流火'])
上述结果中输出的dtype是DataFrame数据的数据类型,int为整型,后面的数字表示位数。
3.2.4 Series的索引
1.Series的索引
- 位置索引是从0开始数,[0]是Series第一个数,[1]是Series第二个数,以此类推。
import pandas as pd
s1=pd.Series([88,60,75])
print(s1[0])
Series不能使用[-1]定位索引。
2.Series标签索引
- Series标签索引与位置索引方法类似,用[]表示,里面是索引名称,注意index的数据类型是字符串,如果需要获取多个标签索引值,用[[]]表示(相当于[]中包含一个列表)。
- 通过索引“明日同学”和“七月流火”获取物理成绩,程序代码如下:
import pandas as pd
s1=pd.Series([88,60,75],index=['明日同学','高同学','七月流火'])
print(s1['明日同学']) #通过一个标签索引获取索引值
print(s1[['明日同学','七月流火']]) #通过多个标签索引获取索引值
88
明日同学 88
七月流火 75
dtype: int64
3.Series切片索引
- 用标签索引做切片,包头包尾(即包含索引开始位置的数据,也包含索引结束位置的索引)。
- 通过标签切片索引“明日同学”至“七月流火”获取数据。程序代码如下:
import pandas as pd
s1=pd.Series([88,60,75],index=['明日同学','高同学','七月流火'])
print(s1['明日同学':'七月流火']) #通过切片获取索引值
明日同学 88
高同学 60
七月流火 75
dtype: int64
- 用位置索引做切片,和list列表用法一样,包头不包尾(即包含索引开始位置的数据,不包含索引结束位置的数据)。
import pandas as pd
#位置索引做切片
s2=pd.Series([88,60,75,34,68])
print(s2[1:4])
1 60
2 75
3 34
dtype: int64
3.2.5 获取Series索引和值
- 获取Series索引和值主要使用Series的index和values方法。
import pandas as pd
s1=pd.Series([88,60,75])
print(s1.index)
print(s1.values)
RangeIndex(start=0, stop=3, step=1)
[88 60 75]
3.3 DataFrame对象
- DataFrame是Pandas库中的一种数据结构,它是由多种数据类型的列组成的二维数据结构,类似于Excel、SQL或Series对象构成的字典。DataFrame是最常用的Pandas对象,它与Series对象一样支持多种类型的数据。
3.3.1 图解DataFrame对象
- DataFrame是一个二维表数据结构,由行、列数据组成的表格。DataFrame既有行索引也有列索引,它可以看作是由Series对象组成的字典,不过这些Series对象共用一个索引,如下图所示:
- 处理DataFrame表格数据时,用index表示行或用columns表示列更直观。用这种方式迭代DataFrame的列,代码更易读懂。
- 遍历DataFrame数据,输出成绩表的每一列数据,程序代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130]]
index = [0,1,2]
columns = ['语文','数学','英语']
# 创建DataFrame数据
df = pd.DataFrame(data=data,index=index,columns=columns)
df
for col in df.columns:series = df[col]print(series)
- 从运行结果可知,上述代码返回的其实是Series,如图3.12所示。Pandas之所以提供多种数据结构,其目的就是为了代码易读、操作更加方便。
3.3.2 创建一个DataFrame对象
- 语法如下:
pandas.DataFrame(data,index,columns,dtype,copy)
- 参数说明
– data:表示数据,可以是ndarray数组,series对象、列表、字典等。
– index:表示行标签(索引)
– columns:列标签(索引)。
– dtype:每一列数据的数据类型,其与Python数据类型有所不同,如object数据类型对应的是Python的字符串。表3.1为pandas数据类型与Python数据类型的对应表。
表3.1 数据类型对应表
Pandas dtype | Python type |
---|---|
object | str |
int64 | int |
float64 | float |
bool | bool |
datetime64 | datetime64[ns] |
timedelta[ns] | NA |
category | NA |
- 承接上面
– copy:用于复制数据。
– 返回值:DataFrame - 下面通过两种方法来创建DataFrame,即通过二维数组创建和通过字典创建。
1.通过二维数组创建DataFrame
- 通过二维数组创建成绩表,包括语文、数学和英语,程序代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130]]
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data,columns=columns)
print(df)
语文 数学 英语
0 110 105 99
1 105 88 115
2 109 120 130
2.通过字典创建DataFrame
- 如果通过字典创建DataFrame,需要注意:字典中的value值只能是一维数组或单个的简单数据类型,如果是数组,要求所有数组长度一致;如果是单个数据,则每行都添加相同数据。
- 通过字典创建成绩表,包括语文、数学、英语和班级,程序代码如下:
import pandas as pd
df = pd.DataFrame({'语文':[110,105,99],'数学':[105,88,115],'英语':[109,120,130],'班级':'高一7班'
},index=[0,1,2])
df
- 上述代码中,"班级"的value值是一个单个数据,所以每一行都添加了相同的数据“高一7班”。
3.3.3 DataFrame重要属性和函数
- DataFrame是Pandas一个重要的对象,它的属性和函数很多,下面简单了解DataFrame的几个重要属性和函数。重要属性介绍表3.2所示,重要函数介绍如表3.3所示。
- 表3.2 重要属性
属性 | 描述 | 举例 |
---|---|---|
values | 查看所有元素的值 | df.values |
dtypes | 查看所有元素的类型 | df.dtypes |
index | 查看所有行名、重命名行名 | df.index,df.index=[1,2,3] |
columns | 查看所有列名、重命名列名 | df.columns, df.columns=[‘语’,‘数’,‘外’] |
T | 行列数据转换 | df.T |
head | 查看前n条数据,默认5条 | df.head(),df.head(10) |
tail | 查看后n条数据,默认5条 | df.tail(),df.tail(10) |
shape | 查看行数和列数,[0]表示行,[1]表示列 | df.shape[0] df.shape[1] |
info | 查看索引,数据类型和内存信息 | df.info |
- 表3.3 重要函数
函数 | 描述 | 举例 |
---|---|---|
describe | 查看每列的统计汇总信息,DataFrame类型 | df.describe() |
count | 返回每一列中的非空的个数 | df.count() |
sum | 返回每一列的和,无法计算返回空值 | df.sum() |
max | 返回每一列的最大值 | df.max() |
min | 返回每一列的最小值 | df.min() |
argmax | 返回值最大值所在的自动索引位置 | df.argmax() |
argmin | 返回最小值所在的自动索引位置 | df.argmin() |
idxmax | 返回最大值所在的自定义索引位置 | df.idxmax() |
idxmin | 返回最小值所在的自定义索引位置 | df.idxmin() |
mean | 返回每一列的平均值 | df.mean() |
median | 返回每一列的中位数 | de.median() |
var | 返回每一列的方差 | df.var() |
std | 返回每一列的标准差 | df.std() |
isnull | 检查df中的空值,空值为True;否则为False,返回布尔型数组 | df.isnull() |
notnull | 检查df的空值,非空值为True;否则False,返回的布尔型数组 | df.notnull() |
3.4 导入外部数据
- 数据分析首先就要由数据。那么,数据类型有多种,本节介绍如何导入不同的外部数据。
3.4.1导入.xls或.xlsx文件
- 导入.xls或.xlsx文件主要使用Pandas的read_excel()方法,语法如下:
pandas.read_excel(io,sheet_name=0,header=None,index_col=None,usecols=None,squeeze=False,dtype=None,engine=None,converters=None,true_values=None,false_values=None,skiprows=None,nrows=None,na_values=None,keep_default_na=True,verbose=False,parse_dates=False,date_parser=None,thousands=None,comment=None,skipfooter=0,convert_float=True,mangle_dupe_cols=True,**kwds)
- 常用参数说明:
– io:字符串,.xls或.xlsx文件路径或类文件对象
– sheet_name:None、字符串、整数、字符串列表或整数列表,默认值为0。字符串用于工作表名称,整数为索引表示工作表位置,字符串列表或整数列表用于请求多个工作表,为None时获取所有所有工作表。参数值如表3.4所示。 - 表3.4 sheet_name参数值
值 | 说明 |
---|---|
sheet_name=0 | 第一个Sheet页中的数据作为DataFrame |
sheet_name=1 | 第二个Sheet页中的数据作为DataFrame |
sheet_name=“Sheet1” | 名为Sheet1中的Sheet页中的数据作为DataFrame |
sheet_name=[0,1,‘Sheet3’] | 第一个、第二个和名为Sheet3的Sheet页中的数据作为DataFrame |
- 部分参数说明
– header:指定作为列名的行,默认值为0,即取第一行的值为列名。数据为除列名以外的数据;若数据不包含列名,则设置header=None。
– names:默认值为None,要使用的列名列表。
– index_col:指定列为索引列,默认值为None,索引0是DataFrame的行标签。
– usecols:int、list列表或字符串,默认值为None。如果为None,则解析所有列。如果为int,则解析最后一列。如果为list列表,则解析列号列表的列。如果为字符串,则表示以逗号分隔的Excel列字母和列范围列表(例“A:E”或“A,C,E:F”)。范围包括双方。 - squeeze:布尔值,默认值为False,如果解析的数据只包含一列,则返回一个Series。
- dtype:列的数据类型名称或字典,默认值为None。例如{‘a’:np.float64,‘b’:np.int32}。
- skiprows:省略指定行数的数据,从尾部数的行开始。
- 下面通过示例,详细介绍如何导入.xlsx文件。
1.常规导入
- 导入“1月.xlsx”Excel文件,程序代码如下:
import pandas as pd
df = pd.read_excel('1月.xlsx')
df.head()
- 默认导入的是“1月.xlsx”文件下的第一个Sheet表。
导入外部数据,必然要涉及路径问题,下面来了解一下相对路径和绝对路径。相对路径就是以当前文件为基准进行一级目录指向被引用的资源文件。以下是常用的表示当前目录和当前目录的父级目录的表示符。
…/:表示当前文件所在目录的上一级目录。
./:表示当前文件所在的目录(可以省略)
/:表示当前文件所在的根目录(域名映射或硬盘目录)。
如果使用系统默认文件路径,那么,在Python中则需要在路径最前面加一个r,以避免系统路径里面的\被转义。
绝对路径:绝对路径是文件真正存在的路径,是指从硬盘的根目录(盘符)开始,进行一级目录指向文件。
2.导入指定的Sheet页
- 一个Excel文件包含多个Sheet页,通过设置sheet_name参数就可以指定Sheet页的数据。
- 一个Excel表包含多家店铺的销售数据,导入其中一家店铺(莫寒)的销售数据,如下图:
- 程序代码如下:
import pandas as pd
df=pd.read_excel('1月.xlsx',sheet_name='莫寒')
df1=df.head() #输出前5条数据
- 除了指定Sheet页的名字,还可以指定Sheet页的顺序,从0开始。例如,sheet_name=0表示导入第一个Sheet页的数据,sheet_name=1表示导入第二个Sheet页的数据,以此类推。
- 如果不指定sheet_name参数,则默认导入Sheet页的数据。
3.通过行、列索引导入指定行、列数据
- DataFrame是二维数据结构,因此它既有行索引又有列索引。当导入Excel数据时,行索引会自动生成,如0、1、2;而列索引则默认将第0行作为列索引(如A,B,…,J)。DataFrame行、列索引的示意图如图3.16所示。
- **如果通过指定行索引导入Excel数据,则需要设置index_col参数。**下面将“买家会员名”作为行索引(位于第0列),导入Excel数据,程序代码如下:
import pandas as pd
df1=pd.read_excel('1月.xlsx',index_col=0) #设置“买家会员名”为行索引
df1.head()
- 如果通过指定列索引导入Excel数据,则需要设置header参数,主要代码如下:
df2=pd.read_excel('1月.xlsx',header=1) #设置第1行为列索引
df2.head()
- 如果将数字作为列索引,可以设置header参数为None,主要代码如下:
df3=pd.read_excel('1月.xlsx',header=None) #列索引为数字
df3.head()
- 那么,为什么要指定索引呢?因为通过索引可以快速地检索数据,例如df3[0],就可以快速检索到“买家会员名”这一列数据。
print(df3[0])
print(df1.loc['mrhy1'])
4. 导入指定列数据
- 一个Excel往往包含多列数据,如果只需要其中的几列,可以通过usecols参数指定需要的列,从0开始(表示第1列,依次类推)。
- 下面导入第1列数据(索引为0),程序代码如下:
import pandas as pd
df1=pd.read_excel('1月.xlsx',usecols=[0]) #通过指定列索引号导入第1列
df1=df1.head()
df2 = pd.read_excel('1月.xlsx', usecols=[0, 3]) #通过指定列索引号导入第1列、第4列
df2=df2.head()
df3=pd.read_excel('1月.xlsx',usecols=['买家会员名','宝贝标题']) #通过指定列名导入指定列
df3=df3.head()
3.4.2 导入.csv文件
- 导入.csv文件主要使用Pandas的read_csv()方法,语法如下:
pandas.read_csv(filepath_or_buffer,sep=',',delimiter=None,header='infer',names=None,index_col=None,usecols=None,squeeze=False,prefix=None,mangle_dupe_cols=True,dtype=None,engine=None,converters=None,true_values=None,false_values=None,skipinitialspace=False,skiprows=None,nrows=None,na_values=None,keep_default_na=True,na_filter=True,verbose=False,skip_blank_lines=True,parse_dates=False,infer_datetime_format=False,keep_date_col=False,date_parser=None,dayfirst=False,iterator=False,chunksize=None,compression='infer',thousands=None,decimal=b'.',lineterminator=None,quotechar="",quoting=0,escapechar=None,comment=None,encoding=None)
- 常用参数说明:
– filepath_or_buffer:字符串,文件路径,也可以是URL链接。
– sep、delimiter:字符串,分隔符。
– header:指定作为列名的行,默认值为0,即取第1行的值为列名。数据为除列名以外的数据;若数据不包含列名,则设置header=None。
– names:默认值为None,要使用的列名列表。
– index_col:指定列为索引列,默认值为None,索引0是DataFrame的行标签。
– usecols:int、list列表或字符串,默认值为None。如果为None,则解析所有列。如果为int,则解析所有列。如果为list列表,则解析列号列表的列。如果为字符串,则表示以逗号分隔的Excel列字母和列范围列表(例如“A:E”或“A,C,E:F”)。范围包括双方。
– dtype:列的数据类型名称或字典,默认值为None。例如{‘a’:np.float64,‘b’:np.int32}。
– parse_dates:布尔值型值、int类型值的列表或字典,默认值为False。可以通过parse_dates参数直接将某列转换成datetime64日期类型。例如,df1=pd.read_csv(‘1月.csv’,parse_dates=[‘订单付款时间’])。
– parse_dates为True时,尝试解析索引。
– parse_dates为int类型值组成的列表时,如[1,2,3],则解析1,2,3列的值作为独立的日期列。
– parse_date为列表组成的列表,如[[1,3]],则将1、3列合并,作为一个日期列使用。
– parse_date为字典时,如{‘总计’:[1,3]},则将1、3列合并,合并后的列名为“总计”。
– encoding:字符串,默认值为None,文件的编码格式。Python常用的编码格式是UTF-8。 - 导入.csv文件,程序代码如下:
import pandas as pd
df1=pd.read_csv('1月.csv',encoding='gbk') #导入csv文件,并指定编码格式
df1=df1.head() #输出前5条数据
df1
3.4.3 导入.txt文本文件
- 导入.txt文件同样使用Pandas的read_csv()方法,不同的是需要指定sep参数(如制表符\t)。read_csv()方法读取.txt文件返回一个DataFrame,像表格一样的二维数据结构。
- 下面使用read_csv()方法导入1月.txt文件,主要代码如下:
import pandas as pd
df1=pd.read_csv('1月.txt',sep='\t',encoding='gbk')
df1=df1.head()
df1
3.4.4 导入HTML网页
- 导入HTML网页数据主要使用Pandas的read_html()方法,该方法用于导入带有table标签的网页表格数据,语法如下:
pandas.read_html(io,match='.+',flavor=None,header=None,index_col=None,skiprows=None,attrs=None,parse_dates=False,thousands=',',encoding=None,decimal='.',converters=None,na_values=None,keep_default_na=True,displayed_only=True)
- 常用参数说明:
– io:字符串,文件路径,也可以是URL链接。网址不接受https,可以尝试去掉https中的s后爬取,如。
– match:正则表达式,返回与正则表达式匹配的表格。
– flavor:解析器默认为lxml。
– header:指定列标题所在的行,列表list为多重索引。
– encoding:字符串,默认为None,文件的编码格式。
– 返回值:返回一个DataFrame。 - 使用read_html()方法前,首先要确定网页表格是否为table类型。例如,NBA球员薪资网页(),查看代码中是否有表格标签
<table>...</table>
的字样,如图3.25所示。确定后才可以使用read_html()方法。
- 下面使用read_html()方法导入NBA球员薪资数据,程序代码如下:
import pandas as pd
df = pd.DataFrame()
url_list = ['']
for i in range(2, 13): #获取第2页到12页的网址url = '/%s/seasontype/4' % iurl_list.append(url)
#遍历网页中的table读取网页表格数据
for url in url_list:df = df.append(pd.read_html(url), ignore_index=True) #拼接表格
#列表解析:遍历dataframe第3列,以子字符串$开头
df = df[[x.startswith('$') for x in df[3]]]
print(df)
df.to_csv('NBA.csv',header=['RK','NAME','TEAM','SALARY'], index=False)
- 运行结果如下:
3.5 数据抽取
-
数据分析过程中,并不是所有的数据都是我们想要的,此时可以抽取部分数据,主要使用DataFrame对象的loc属性和iloc属性,示意图如图3.27所示。
-
对象的loc属性和iloc属性都可以抽取数据,区别如下。
– loc属性:以列名(columns)和行名(index)作为参数,当只有一个参数,默认是行名,即抽取整行数据,包含所有列,如df.loc[‘A’]。
– iloc属性:以行和列位置索引(即0,1,2,…)作为参数,0表示第1行,1表示第2行,依次类推。当只有一个参数时,默认是行索引,即抽取整行数据,包含所有列。如抽取第1行数据,df.iloc[0]。
3.5.1 抽取一行数据
- 抽取一行数据主要使用loc属性。
- 抽取一行名为"明日"的考试成绩(包括所有列),程序代码如下:
import pandas as pd
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
df
df1=df.loc['明日']
#df1=df.iloc[0]
df1
3.5.2 抽取多行数据
1.抽取任意多行数据
- 通过loc属性和iloc属性指定行名和行索引即可实现任意多行数据。
- 抽取名为"明日"和"高袁圆"(即第1行和第3行数据)的考试成绩数据,可以使用loc属性,也可以使用iloc属性,其输出结果都是一样的,主要代码如下:
- 连续抽取几个学生的考试成绩,主要代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)#抽取连续任意多行数据
print(df.loc['明日':'二月二']) #从“明日”到“二月二”
print(df.loc[:'七月流火']) #第1行到“七月流火”
print(df.iloc[0:4]) #第1行到第4行
print(df.iloc[1::]) #第2行到最后1行
3.5.3 抽取指定列数据
- 抽取指定列数据,可以直接使用列名,也可以使用loc属性和iloc属性。
1.直接使用列名
- 抽取列名为“语文”和“数学”的考试成绩数据,程序代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
df
df1 = df[['语文','数学']]
df1
- 如果只是选择某一列,可以使用下面这种方式:
2.使用loc属性和iloc属性
- 前面介绍loc属性和iloc属性均有两个参数:第一个参数代表行;第二个参数代表列。那么这里抽取指定列数据时,行参数不能省略。
- 下面使用loc属性和iloc属性抽取指定列数据,主要代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)#抽取指定列数据——使用loc方法和iloc方法,注意loc与iloc的区别
print(df.loc[:,['语文','数学']]) #抽取“语文”和“数学”
print(df.iloc[:,[0,1]]) #抽取第1列和第2列
print(df.loc[:,'语文':]) #抽取从“语文”开始到最后一列
print(df.iloc[:,:2]) #连续抽取从1列开始到第3列
3.5.4 抽取指定行、列数据
- 抽取指定行、列数据主要使用loc属性和iloc属性,这两个方法的两个参数都指定就可以实现指定行、列数据的抽取。
- 使用loc属性和iloc属性抽取指定行、列数据,程序代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)#抽取指定行列数据
print(df.loc['七月流火','英语']) #“英语”成绩
print(df.loc[['七月流火'],['英语']]) #“七月流火”的“英语”成绩
print(df.loc[['七月流火'],['数学','英语']]) #“七月流火”的“数学”和“英语”成绩
print(df.iloc[[1],[2]]) #第2行第3列
print(df.iloc[1:,[2]]) #第2行到最后一行的第3列
print(df.iloc[1:,[0,2]]) #第2行到最后一行的第1列和第3列
print(df.iloc[:,2]) #所有行,第3列
df.iloc[1:,1:] #提取第二行到最后一行的第二列到最后一列数据
df.loc['七月流火':,'数学':]#提取第二行到最后一行的第二列到最后一列数据
- 在上述结果中,第一个输出结果是一个数,不是数据,是由于“df.loc[‘七月流火’,‘英语’]”没有使用方括号[],导致输出的的数据不是DataFrame类型。
- 具体区别详见下面这个截图:
3.5.5 按指定条件抽取数据
- DataFrame对象实现数据查询有以下3中方式。
– 取其中的一个元素.iat[x,x]。
– 基于位置的查询,如.iloc[]、iloc[2,1]
– 基于行、列名称的查询,如.loc[x] - 抽取语文成绩大于105,数学成绩大于88的数据,程序代码如下:
import pandas as pddata = [[110,105,99],[105,88,115],[109,120,130],[112,115]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)#按指定条件抽取数据
df1=df.loc[(df['语文'] > 105) & (df['数学'] >88)]
3.6 数据的增加、修改和删除
- 本节主要介绍如何操纵DataFrame对象中的各种数据。例如,数据的增加、修改和删除。
3.6.1 增加数据
- DataFrame对象增加数据主要包括数据增加和行数据增加。首先看一下原始数据,如图3.35所示。
1.按列增加数据
- 按列增加数据,可以通过以下3中方式实现。
- (1)直接为DataFrame对象赋值
- 增加一列“物理”成绩,程序代码如下:
import pandas as pd
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,140]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
df
#增加数据——按列增加数据
df['物理']=[88,79,60,50]
df
- (2)使用loc属性在DataFrame对象的最后增加一列
- 使用loc属性在DataFrame对象的最后增加一列。例如,增加“物理”一列,主要代码如下:
df.loc[:,'物理'] = [88,79,60,50]
df
2.按行增加数据
- 按行增加数据,可以通过一下两种方式实现。
- (1)增加一行数据
-
- 增加一行数据主要使用loc属性实现。
- 在成绩表中增加一行数据,即“钱多多”同学的成绩,主要代码如下:
df.loc['钱多多'] = [100,120,99]
df
- (2)增加多行数据
-
- 增加多行数据主要使用字典结合append()方法实现。
- 在原有数据中增加“钱多多”“童年”“无名”同学的考试成绩,主要代码如下:
df_insert = pd.DataFrame({'语文':[100,123,138],'数学':[99,142,60],'英语':[98,139,99]},index=['钱多多','童年','无名'])
df1 = df.append(df_insert)
df1
3.6.2 修改数据
- 修改数据包括行、列标题和数据的修改,首先看一下原始数据,如下图所示:
1.修改列标题
- 修改列标题主要使用DataFrame对象的coloums属性,直接赋值即可。
- 将“数学”修改为“数学(上)”,主要代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,140]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)df.columns=['语文','数学(上)','英语']
- 上述代码中,即使只修改“数学”为“数学(上)”,但是也要将所有列的标题全部加上;否则将报错。
- 下面再介绍一种方法,使用DataFrame对象的rename()方法修改列标题。
- 将“语文”修改为“语文(上)”、“数学”修改为“数学(上)”、“英语”修改为“英语(上)”,主要代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,140]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
df.rename(columns = {'语文':'语文(上)','数学':'数学(上)','英语':'英语(上)'},inplace = True)
- 上述代码中,参数inplace为True,表示直接修改df;否则,不修改df,只返回修改后的数据。
2.修改行标题
- 修改行标题主要使用DataFrame对象的index属性,直接赋值即可。
- 将行标题统一修改为数字编号,主要代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,140]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
df.index=list('1234')
#也可以使用rename属性
#df.rename({'明日':1,'七月流火':2,'高袁圆':3,'二月二':4},axis=0,inplace = True)
3.修改数据
- 修改数据主要使用DataFrame对象的loc属性和iloc属性。
- (1)修改整行数据
– 例如,修改“明日”同学的各科成绩,主要代码如下:
import pandas as pd
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,140]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
#修改整行数据
df.loc['明日']=[120,115,109]
#各科成绩均加10分
df.loc['明日']=df.loc['明日']+10
- (2)修改整列数据
– 例如,修改所有同学的“语文”成绩,主要代码如下:
#修改整列数据
df.loc[:,'语文']=[115,108,112,118]
- (4)使用iloc属性修改数据
- 通过iloc指定行、列位置实现修改数据,主要代码如下:
#使用iloc方法修改数据
df.iloc[0,0]=115 #修改某一数据
df.iloc[:,0]=[115,108,112,118] #修改整列数据
df.iloc[0,:]=[120,115,109] #修改整行数据
3.6.3 删除数据
- 删除数据主要使用DataFrame对象的drop()方法。语法如下:
DataFrame.drop(labels=None,axis=0,index=None,columns=None,level=None,inplace=None,errors='raise')
- 参数说明
– labels:表示行标签或列标签
– axis:axis=0,表示按行删除;axis=1,表示按列删除。默认值为0,即按行删除。
– index:删除行,默认值为None
– level:针对有两级索引的数据。level=0,表示按第1级索引删除整行;level=1表示按第2级索引删除整行,默认值为None
– inplace:可选参数,对原数组做出修改并返回一个新数组。默认值为False,如果值为True,那么原数组直接就被替换
– errors:参数值为ignore或raise,默认值为raise,如果值为ignore(忽略),则取消错误。
1.删除行、列数据
- 删除指定的学生成绩数据,主要代码如下:
#删除行列数据
df.drop(['数学'],axis=1,inplace=True) #删除某列
df.drop(columns='数学',inplace=True) #删除columns为“数学”的列
df.drop(labels='数学', axis=1,inplace=True) #删除列标签为“数学” 的列
df.drop(['明日','二月二'],inplace=True) #删除某行
df.drop(index='明日',inplace=True) #删除index为“明日”的行
df.drop(labels='明日', axis=0,inplace=True) #删除行标签为“明日”的行
2. 删除特定条件的行
- 删除满足特定条件的行,首先找到满足该条件的行索引,然后再使用drop()方法将其删除。
- 删除“数学”成绩中包含88的行、“语文”成绩中小于110的行,主要代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,140]]
name = ['明日','七月流火','高袁圆','二月二']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)#删除特定条件的行
df.drop(index=df[df['数学'].isin([88])].index[0],inplace=True) #删除“数学”包含88的行
df.drop(index=df[df['语文']<110].index[0],inplace=True) #删除“语文”小于110的行
3.7 数据清洗
3.7.1 缺失值查看与处理
- 缺失值是指由于某种原因导致数据为空,这种情况一般有不处理、删除、填充/替换、插值(以均值/中位数/众数等填补)这4种处理方式。
1.缺失值查看(info()和isnull()方法)
- 首先需要找到缺失值,主要使用DataFrame对象的info()方法。
- 以淘宝销售数据为例,首先输出数据,然后使用info()方法查看数据,程序代码如下:
import pandas as pd
df=pd.read_excel('TB2018.xls')
df
print(df.info())
- 在Python中,缺失值一般用NaN表示,通过info()方法可看到“买家会员名”“买家实际支付金额”“宝贝标题”“订单付款时间”的非空数量是10,而“宝贝总数量”和“类别”的非空数量是8,那么说明这两项存在空值。
- 接下来判断数据是否存在空值还可以使用isnull()方法和notnull()方法,主要代码如下:
print(df.isnull())
print(df.notnull())
- 使用isnull()方法缺失值返回True,非缺失值返回False;而notnull()方法与isnull()方法正好相反,缺失值返回False,非缺失值返回True。
- 如果使用df[df.isnull()==False],则会将所有非缺失值都找出来,只针对Series对象。
2.缺失值删除处理(删除所有空行、过滤特定列的空值所在行)
- 通过前面的判断得知数据缺失情况,下面将缺失值删除,主要使用dropna()方法,该方法用于删除含有缺失值的行,主要代码如下:
df1=df.dropna()
df1
有些时候数据可能存在整行为空的情况,此时可以在dropna()方法中指定参数how=‘all’,删除所有空行。
- 从运行结果得知:dropna()方法将所有包含缺失值的数据全部删除了。那么,此时如果我们认为有些数据虽然存在缺失值,但是不影响数据分析,那么可以使用一下方法处理。例如上述数据中只保留“宝贝总数量”不存在缺失值的数据,而类别是否存在缺失不关注,则可以使用notnull()方法判断,主要代码如下:
df2 = df[df['宝贝总数量'].notnull()]
df2
3. 缺失值填充处理
- 对于缺失数据,如果比例高于30%可以选择放弃这个指标,做删除处理;低于30%尽量不要删除,而是选择将这部分数据填充,一般是0、均值、众数(大多数)填充。DataFrame对象中的fillna()函数可以实现填充缺失数据,pad/ffilll表示用前一个非缺失值去填充该缺失值;backfill/bfill表示用下一个非缺失值填充该缺失值;None用于指定一个值去替换缺失值。
- 对于用于计算的数值型数据如果为空,可以选择用0填充。例如,将“宝贝总数量”为空的数据填充为0,主要代码如下:
df['宝贝总数量'] = df['宝贝总数量'].fillna(0)
df
3.7.2 重复值处理
- 对于数据中存在的重复数据,包括重复的行或者几行中某几列的值重复一般做删除处理,主要使用DataFrame对象的drop_duplicates()方法。
- 下面以“1月.xlsx”淘宝销售数据为例,对其中的重复数据进行处理。
- (1)判断每一行数据是否重复(完全相同),主要代码如下:
df1.duplicated()
- 如果返回值为False表示不重复,返回值为True表示重复。
- (2)去除全部的重复数据,主要代码如下:
df1.drop_duplicates()
df1
- (3)去除指定列的重复数据,主要代码如下:
df1.drop_duplicates(['买家会员名'])
- (4)去除全部的重复数据,主要代码如下:
df1.drop_duplicates(['买家会员名'],keep='last')
以上代码中参数keep的值有3个,当keep='first’表示保留第一次出现的重复行,是默认值;当keep为另外两个取值,即last或False时,分别表示保留最后一次出现的重复行和去除所有重复行。
- (5)直接删除,保留一个副本,主要代码如下:
df1.drop_duplicates(['买家会员名','买家支付宝账号'],implace=False)
- implace=True表示直接在原来的DataFrame上删除重复值,而默认值False表示删除重复项后生成一个副本。
3.7.3 异常值的检测与处理
- 首先了解一下什么是异常值。在数据分析中异常值是指超出或低于正常范围的值,如年龄大于200、身高大于3米、宝贝总数量为负数等类似数据。那么这些数据如何检测呢?主要有以下几种方法。
- (1)根据给定的数据范围进行判断,不在范围内的数据视为异常值。
- (2)均方差。在统计学中,如果一个数据分布近似正态分布,那么大约68%的数据值会在均值的一个标准差范围内,大约95%会在两个两个标准差范围内,大于99.7%会在3个标准差范围内。
- (3)箱型图。箱型图是显示一组数据分散情况资料的统计图。它可以将数据通过四分位数的形式进行图形描述。箱型图通过上限和下限作为数据分布的边界。任何高于上限或低于下限的数据都可以认为是异常值,如图3.48所示。
有关箱型图的介绍以及如何通过箱型图识别异常值可参见第6章。
- 了解了异常值的检测,接下来介绍如何处理异常值,主要包括以下几种处理方式。
- (1)最常用的处理方式就是删除。
- (2)将异常值当作缺失值处理,以某个值填充。
- (3) 将异常值当特殊情况进行分析,研究异常值出现的原因。
3.8 索引设置
- 索引能够快速查询数据,本节主要介绍索引的作用以及索引的应用。
3.8.1 索引的作用
- 索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。Pandas索引的作用如下。
– 更方便查询数据。
– 使用索引可以提升查询性能。
– 如果索引是唯一的,Pandas会使用哈希表优化,查找数据的时间复杂度为O(1).
– 如果索引是完全随机的,那么每次查询都要扫描数据表,查找数据的时间复杂度为O(N)。 - 自动的数据对齐功能,示意图如图3.49所示。
- 实现上述效果,程序代码如下:
import pandas as pd
s1 = pd.Series([10,20,30],index=list('abc'))
s2 = pd.Series([2,3,4],index=list('bcd'))
s1+s2
- 强大的数据结构。
– 基于分类数的索引,提升性能。
– 多维索引,用于groupby多维聚合结果等。
– 时间类型索引,强大的日期和时间的方法支持。
3.8.2 重新设置索引
- Pandas有一个很重要的方法是reindex(),它的作用是创建一个适应新索引的新对象。语法如下:
DataFrame.reindex(labels=None,index=None,columns=None,axis=None,method=None,copy=True,level=None,fill_value=nan,limit=None,tolerance=None)
- 常用参数说明:
– labels:标签,可以是数组,默认值为None(无)。
– index:行索引,默认值为None。
– columns:列索引,默认值为None。
– axis:轴,axis=0,表示行,axis=1表示列。默认值为None
– method:默认值为None,重新设置索引时,选择插值方法,其值可以是None,bfill/backfill(向后填充)、fill/pad(向前填充)等。
– fill_value:缺失值要填充的数据。如缺失值不用NaN填充,而用0填充,则设置为fill_value=0即可。
1. 对Series对象重新设置索引
- 在3.2.3节已经建立了一组学生的物理成绩,下面重新设置索引,程序代码如下:
from pandas import Series
#从pandas引入Series对象,就可以直接使用Series对象了,如Series([88,60,75],index=[1,2,3])
s1=Series([88,60,75],index=[1,2,3])
s1
s1.reindex([1,2,3,4,5])
- 从运行结果可知:reindex()方法根据新索引进行了重新排序,并且对缺失值自动填充NaN。如果不想用NaN填充,则可以为fill_value参数指定值,如0,主要代码如下:
s1.reindex([1,2,3,4,5],fill_value=0)
- 而对于一些有一定顺序的数据,我们可能需要插值来填充缺失的数据,可以使用method参数。
- 向前填充、向后填充,主要代码如下:
s1.reindex([1,2,3,4,5],method='ffill') #向前填充(和前面数据一样)
s1.reindex([1,2,3,4,5],method='bfill') #向后填充(和后面数据一样)
2.对DataFrame对象重新设置索引
- 对于DataFrame对象,reindex()方法用于修改行索引和列索引。
- 通过二维数组创建成绩表,程序代码如下:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130]]
index=['mr001','mr003','mr005']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=index,columns=columns)
df
- 通过reindex()方法重新设置行索引,主要代码如下:
df.reindex(['mr001','mr002','mr003','mr004','mr005'])
- 通过reindex()方法重新设置列索引,主要代码如下:
df.reindex(columns=['语文','物理','数学','英语'])
- 通过reindex()方法重新设置行索引和列索引,主要代码如下:
df.reindex(index=['mr001','mr002','mr003','mr004','mr005'],columns=['语文','物理','数学','英语'])
3.8.3 设置某列为行索引
- 设置某列为行索引主要使用set_index()方法。
- 首先,导入“1月.xlsx”Excel文件,程序代码如下:
import pandas as pd
df=pd.read_excel('1月.xlsx')
df1=df.head()
df1
#设置“买家会员名”为行索引
df=df.set_index(['买家会员名'])
df2=df.head()
df2
- 如果在set_index()方法中传入参数drop=True,则会删除“买家会员名”;如果传入drop=False,则会保留“买家会员名”。默认为False。
3.8.4 数据清洗后重新设置连续的行索引
- 在对DataFrame对象进行数据清洗后,例如去掉行NaN的行之后,发现行索引还是原来的行索引,对比效果如图3.58和图3.59所示。
- 如果要重新设置索引可以使用reset_index()方法,在删除缺失数据后重新设置索引,主要代码如下:
import pandas as pd
df=pd.read_excel('TB2018.xls')
df
df1=df.dropna() #删除含有缺失值的所在行
df1
df2=df.dropna().reset_index(drop=True)
df2
- 另外,对于分组统计后的数据,有时也需要重新设置连续的行索引,方法同上。
3.9 数据排序与排名
- 本节主要介绍数据的各种排序和排名方法。
3.9.1 数据排序
- DataFrame数据排序主要使用sort_values()方法,该方法类似于SQL中的ORDER BY。sort_values()方法可以根据指定行列进行排序,语法如下:
DataFrame.sort_values(by,axis=0,ascending=True,inplace=False,kind='quiksort',na_position='last',ignore_index=False)
- 参数说明
– by:要排序的名称列表
– axis:轴,axis=0表示行,axis=1表示列。默认值为0,即按行排序。
– ascending:升序或降序,布尔值,指定多个排序可以使用布尔值列表。默认值为True。
– kind:指定排序算法,值为quicksort(快速排序)、mergesort(混合排序)或heapsort(堆排),默认值为quicksort。
– na_position:空值(NaN)的位置,值为first空值在数据开头,值为last空值在数据最后,默认值为last
– ignore_index:布尔值,是否忽略索引,值为True标记索引(从0开始按顺序的整数值),值为False则忽略索引。
1.按一列数据排序
- 按“销量”降序排序:
import pandas as pd
excelFile = 'mrbook.xlsx'
df = pd.DataFrame(pd.read_excel(excelFile))
df
#按“销量”列降序排序
df=df.sort_values(by='销量',ascending=False)
df
2. 按多列数据排序
- 多列排序是按照给定列的先后顺序进行排序的。
- 按照“图书名称”和“销量”降序排列,首先按“图书名称”降序排列,然后再按“销量”降序排序,排序后的效果如下图所示:
#按“图书名称”和“销量”列降序排序
df1=df.sort_values(by=['图书名称','销量'],ascending=False)
3.对统计结果排序
- 按“类别”分组统计销量并进行降序排序,统计排序后的效果如下图所示。
import pandas as pd
excelFile = 'mrbook.xlsx'
df = pd.DataFrame(pd.read_excel(excelFile))
df
df1=df.groupby(["类别"])["销量"].sum().reset_index()
df1
df2=df1.sort_values(by='销量',ascending=False)
df2
4.按行数据排序
- 按行排序,主要代码如下:
#按照索引值为0的行,即第一行的值升序排序
df=dfrow.sort_values(by=0,ascending=True,axis=1)
df
按行排序的数据类型要一致,否则会出现错误提示。
3.9.2 数据排名
- 排名是根据Series对象或DataFrame的某几列的值进行排名的,主要使用rank()方法,语法如下:
DataFrame.rank(axis=0,method='average',numeric_only=None,na_option='keep',ascending=True,pct=False)
- 参数说明:
– axis:轴,axis=0表示行,axis=1表示列。默认值为0,即按行排序。
– method:表示在具有相同值的情况下所使用的排序方法。设置值如下。average:默认值,平均排名。min:最小值排名。max:最大值排名。first:按值在原始数据中的出现顺序分配排名。dense:密集排名,类似最小值排名,但是排名每次只增加1,即排名相同的数据只占一个名次。
– numeric_only:对于DataFrame对象,如果设置值为True,则只对数字列进行排序。
– na_option:空值的排序方式,设置值如下。keep:保留,将空值等级赋值给NaN值。top:如果按升序排序,则将最小排名赋值给NaN值。bottom:如果按升序排序,则将最大排名赋值给NaN。
– ascending:升序或降序排序,布尔值,指定多个排序可以使用布尔值列表。默认值为True。
– pic:布尔值,是否以百分比形式返回排名。默认值为False。
1. 顺序排名
- 下面对销量相同的产品,按照出现的顺序排名,程序代码如下:
import pandas as pd
excelFile = 'mrbook.xlsx'
df = pd.DataFrame(pd.read_excel(excelFile))
df
#按“销量”列降序排序
df=df.sort_values(by='销量',ascending=False)
df
# 顺序排名
df['顺序排名'] = df['销量'].rank(method="first", ascending=False)
df1=df[['图书名称','销量','顺序排名']]
df1
2.平均排名
- 现在对销量相同的产品,按照顺序排名的平均值作为平均排名,主要代码如下:
#平均排名
df['平均排名']=df['销量'].rank(ascending=False)
df1=df[['图书名称','销量','平均排名']]
df1
3.最小值排名
- 排名相同的,按顺序排名取最小值作为排名:
#最小值排名
df['最小值排名']=df['销量'].rank(method="min",ascending=False)
df_min=df[['图书名称','销量','最小值排名']]
df_min
4.最大值排名
#最大值排名
df['最小值排名']=df['销量'].rank(method="max",ascending=False)
df_max=df[['图书名称','销量','最小值排名']]
df_max
5.密集排名
#排名相同的数据只占一个名称
df['最小值排名']=df['销量'].rank(method="dense",ascending=False)
df_dense=df[['图书名称','销量','最小值排名']]
df_dense
更多推荐
pandas统计分析上(导入excel数据、Series对象、DataFrame对象、绝对路径和相对路径、多个html表格的拼接及排序、loc与iloc的区别、
发布评论