Python数据处理工具——Pandas

目录

一、序列与数据框的构造

 1、构造序列

2、构造数据框

二、外部数据的读取

1、文本文件的读取

2、电子表格的读取

pd.read_excel参数介绍:

三、数据类型转换及描述统计

四、字符与日期数据的处理

五、常用的数据清洗方法

1、重复观测处理

2、缺失值处理

3、异常值处理

六、数据子集的获取

七、透视表功能

八、表之间的合并与连接

九、分组聚合操作


一、序列与数据框的构造

Pandas模块的核心操作对象就是序列(Series)和数据框DataFrame)。

 1、构造序列

使用如下方式实现:

通过同质的列表或元组构建。

通过字典构建。

通过Numpy中的一维数组构建。

import pandas as pd
import numpy as np
data1=pd.Series([2.8,3.01,8.99,8.59,5.18])
data2=pd.Series({'北京':2.8,'上海':3.01,'广东':8.99,'江苏':8.59,'浙江':5.18})
data3=pd.Series(np.array((2.8,3.01,8.99,8.59,5.18)))
print(data1)
print(data2)
print(data3)

通过 Series函数将列表、字典和一维数组转换为序列的过程。
构造的序列结果都是第一个打印的样式。
该样式会 产生两列,
第一列属于序列的行索引(可以理解为行号),自动从0 开 始,第二列才是序列的实际值。
通过字典构造的序列就是第二个打印样式,仍然包含两列,所不同的是第一列不再是行号,而是具体的行名称 (label),对应到字典中的键,第二列是序列的实际值,对应到字典中 的值。

序列与一维数组有极高的相似性.

  • 不同的是,序列会有更多的其他处理方法。
  • 下面通过几个 具体的例子来加以测试:
print('行号风格的序列:\n',data1[[0,3,4]],'\n')
print('行名称风格的序列:\n',data2[[0,3,4]],'\n')
print('行名称风格的序列: \n',data2[['上海','江苏','浙江']],'\n')
print('通过numpy函数:\n',np.log(data1),'\n')
print('通过numpy函数:\n',np.mean(data1),'\n')
print('通过序列的方法:\n',data1.mean(),'\n')

        如果需要对序 列进行数学函数的运算,一般首选numpy模块,因为Pandas模块在这方 面比较缺乏;如果是对序列做统计运算,既可以使用numpy模块中的函 数,也可以使用序列的“方法,作者一般首选序列的方法,因为序列 的“方法更加丰富,如计算序列的偏度、峰度等,而Numpy是没有这样的函数的。

这里稍微介绍一下序列的方法,就不演示了:

①检查缺失值;

Series名.isnull()  和  Series名.notnull()   
isnull()   判断索引对应的值是否为空,若为空,返回True。语句返回值为Series类型。

notnull()   判断索引对应的值是否为非空,若为空,返回False。

②通过索引获取数据;

获取索引的方法:Series名.index

获取值的方法:   Series名.values

2.1 获取单个数据

① 通过下标获取        Series名[索引号]  

② 通过标签名获取    Series名[标签名]

2.2 获取多个数据

① 通过下标获取       Series名[[索引号1,索引号2]]    #获取索引号1和2对应的数据

② 通过标签名获取    Series名[[标签名1,标签名2]]  

2.3 切片获取数据

① 通过下标获取        Series名[索引号1:索引号2]      #下标切片顾头不顾尾

② 通过标签名获取    Series名[标签名1:标签名2]      #标签名切片顾头顾尾

③布尔索引;

Series名[条件判断]       

布尔索引可理解为True和False。

如:

s11 = s10[s10>3] #取出s10的值大于3的数据

④name属性;

改变对象的名称:        Series名.name = 自定义名称

改变对象的索引名称: Series名.index.name = 自定义名称

⑤读取前几行数据;

Series名.head()        # 默认读取前5行数据

Series名.head(n)      # 也可自己指定读取前n行

⑥读取后几行数据。

Series名.tail()       # 默认读取后5行数据

Series名.tail(n)     # 也可自己指定读取后n行

感兴趣的可以自己去查还有很多的呢

好了,回归主题,继续介绍pandas

2、构造数据框

  • 数据框中可以存放不同数据类型的序列
  • 而数组和序列则没有这样的优势,因为它们只能存放同质数据。

应用如下方式:

  • 通过嵌套的列表或元组构造。
  • 通过字典构造。
  • 通过二维数组构造。
  • 通过外部数据的读取构造。
# 构造数据框
data1=pd.DataFrame([['张三','23','男'],['李四','27','女'],['王二','26','女']])
data2=pd.DataFrame({'姓名':['张三','李四','王二'],'年龄':['23','27','26'],'性别':['男','女','女']})
data3=pd.DataFrame(np.array([['张三',23,'男'],['李四','27','女'],['王二','26','女']]))
print('嵌套列表构造数据框:\n',data1)
print('字典构造数据框:\n',data2)
print('二维数组构造数据框: \n',data3)

如果需要手工构造数据框的话,一般首选字典方法。因为字典转换数据框时有具体的变量名

 二、外部数据的读取

        很显然,每次通过手工构造数据框是不现实的,在实际工作中,更多的情况则是通过Python读取外部数据集,这些数据集可能包含在本地 的文本文件(如csvtxt等),接下来介绍读取外部文件。

1、文本文件的读取

        当要读取外部文件时。一般使用 Pandas模块中的read_table函数或read_csv函数。这里的并不是指每 个函数只能读取一种格式的数据,而是这两种函数均可以读取文本文件的数据。

这里主要介绍pd.read_table,因为它们的参数都是差不多的。

pd.read_table(filepath_or_buffer,sep='\t',header='infer',names=None,                                
              index_col=None,usecols=None,dtype=None,converters=None,
              skiprows=None,skipfooter=None,nrows=None,na_values=None,            
              skip_blank_lines=True,parse_dates=False,thousands=None,
              comment=None,encoding=None)

pd.read_table参数介绍:

filepath_or_buffer指定txt文件或csv文件所在的具体路径。

sep指定原数据集中各字段之间的分隔符,默认为Tab制表符。

header是否需要将原数据集中的第一行作为表头,默认将第一 行用作字段名称。

names如果原数据集中没有字段,可以通过该参数在数据读取 时给数据框添加具体的表头。

index_col指定原数据集中的某些列作为数据框的行索引(标 签)。

usecols指定需要读取原数据集中的哪些变量名。

dtype读取数据时,可以为原数据集的每个字段设置不同的数 据类型。

converters通过字典格式,为数据集中的某些字段设置转换函 数。

skiprows数据读取时,指定需要跳过原数据集开头的行数。

skipfooter数据读取时,指定需要跳过原数据集末尾的行数。

nrows指定读取数据的行数。

na_values指定原数据集中哪些特征的值作为缺失值。

skip_blank_lines读取数据时是否需要跳过原数据集中的空白 行,默认为True

parse_dates如果参数值为True,则尝试解析数据框的行索引; 如果参数为列表,则尝试解析对应的日期列;如果参数为嵌套列 表,则将某些列合并为日期列;如果参数为字典,则解析对应的 列(字典中的值),并生成新的字段名(字典中的键)。

thousands指定原始数据集中的千分位符。

comment指定注释符,在读取数据时,如果碰到行首指定的注释符,则跳过改行。

encoding如果文件中含有中文,有时需要指定字符编码。

下面举例说明:

这里构造一个稍 微复杂点的数据集用于测试,数据存放在txt 中。

#读取文本文件中的数据
user_income = pd.read_table ('data.txt',sep = ',',parse_dates= { 'birthday':[ 0,1,2] },skiprows=2,skipfooter=3,comment='#',encoding='utf8',thousands='&')
user_income

代码说明:由于read_table函数在读取数 据时,默认将字段分隔符sep设置为Tab制表符,而原始数据集是用逗号 分割每一列,所以需要改变sep参数;parse_dates参数通过字典实现前三 列的日期解析,并合并为新字段birthdayskiprowsskipfooter参数分别 实现原数据集开头几行和末尾几行数据的跳过;由于数据部分的第四行 前面加了#号,因此通过comment参数指定跳过的特殊行;这里仅改变 字符编码参数encoding是不够的,还需要将原始的txt文件另存为UTF-8 格式;最后,对于收入一列,由于千分位符为&,因此为了保证数值型 数据的正常读入,需要设置thousands参数为&

2、电子表格的读取

pd.read_excel(io,sheetname=0,header=0,skiprows=None,skip_footer=0,
              index_col=None,names=None,parse_cols-None,                    
              parse_dates=False,na_values=None,thousands=None,convert_float=True)

pd.read_excel参数介绍:

io指定电子表格的具体路径。

sheetname指定需要读取电子表格中的第几个Sheet,既可以传 递整数也可以传递具体的Sheet名称。

header是否需要将数据集的第一行用作表头,默认为是需要 的。

skiprows读取数据时,指定跳过的开始行数。

skip_footer读取数据时,指定跳过的末尾行数。

index_col指定哪些列用作数据框的行索引(标签)。

names如果原数据集中没有字段,可以通过该参数在数据读取 时给数据框添加具体的表头。

parse_cols指定需要解析的字段。

parse_dates如果参数值为True,则尝试解析数据框的行索引; 如果参数为列表,则尝试解析对应的日期列;如果参数为嵌套列 表,则将某些列合并为日期列;如果参数为字典,则解析对应的 列(字典中的值),并生成新的字段名(字典中的键)。

na_values指定原始数据中哪些特殊值代表了缺失值。

thousands指定原始数据集中的千分位符。

convert_float默认将所有的数值型字段转换为浮点型字段。

converters通过字典的形式,指定某些列需要转换的形式。

三、数据类型转换及描述统计

        内容主要介绍如何了解数据,例如读 入数据的规模如何、各个变量都属于什么数据类型、一些重要的统计指 标对应的值是多少、离散变量各唯一值的频次该如何统计等。下面以泰坦尼克号乘客信息为例:

# 数据读取 
sec_cars = pd.read_table(r'train.csv', sep = ',') 
# 预览数据的前五行 
sec_cars.head()

如上代码中,head方法可以返回 数据集的开头5行;如果读者需要查看数据集的末尾5行,可以使用tail 方法。进一步,如果还想知道数据集有多少观测和多少变量,以及每个 变量都是什么数据类型,可以按如下代码得知:

# 查看数据的行列数
print('数据集的行列数:\n',sec_cars.shape)
#查看数据集每个变量的数据类型
print('各变量的数据类型:\n',sec_cars.dtypes)

 

接下来,需要对数据做到心中有数,即通过基本的统计量(如最小 值、均值、中位数、最大值等)描述出数据的特征。关于数据的描述性 分析可以使用describe方法:

# 数据的描述性统计 
sec_cars.describe()

通过describe方法,直接运算了数据框中所有数值 型变量的统计值,包括非缺失个数、平均值、标

准差、最小值、下四分 位数、中位数、上四分位数和最大值。

以上都是有关数据的统计描述,但并不能清晰地知道数据的形状分布,如数据是否有偏以及是否属

于“尖峰厚尾”的特征,为了一次性统计 数值型变量的偏度和峰度,可以参考如下代码:

#挑出所有数值型变量
num_variables = sec_cars.columns[sec_cars.dtypes !='object'] [1:]#自定义函数,计算偏度和峰度
def skew_kurt(x):
    skewness = x.skew ()
    kurtsis =x.kurt()
    #返回偏度值和峰度值
    return pd.Series( [skewness, kurtsis], index = [ 'Skew', 'Kurt'])
#运用apply方法
sec_cars[num_variables ].apply(func = skew_kurt,axis = 0)

如上结果所示正是每个数值型变量的偏度和峰度,这三个变量都属 于右偏(因为偏度值均大于0),而且三个变量也是尖峰的(因为峰度 值也都大于0)。

代码说明:columns方法用于返回数据集的所有变量 名,通过布尔索引和切片方法获得所有的数值型变量;在自定义函数 中,运用到了计算偏度的skew方法和计算峰度的kurt方法,然后将计算 结果组合到序列中;最后使用apply方法,该方法的目的就是对指定轴 (axis=0,即垂直方向的各列)进行统计运算(运算函数即自定义函 数)。

以上的统计分析全都是针对数值型变量的,对于数据框中的字符型变量,该如何做统计描述

呢?仍然可以使用describe方法,所不同的是,需要设置该方法中的

include参数,具体代码如下:

# 离散型变量的统计描述 
sec_cars.describe(include = ['object'])

对于离散型变量,运用describe方法只能得知哪个离散水平属于明 星”值。如果读者需要统计的是

各个离散值的频次,甚至是对应的频率,该如何计算呢?这里直接给出如下代码(Sex为例):

# 离散变量频次统计 
Freq = sec_cars.Sex.value_counts() 
Freq_ratio = Freq/sec_cars.shape[0] 
Freq_df = pd.DataFrame({'Freq':Freq,'Freq_ratio':Freq_ratio}) 
Freq_df.head()

如果需要把行标签设置为数据框中的列,可以使用 reset_index方法,具体操作如下:

# 将行索引重设为变量 
Freq_df.reset_index(inplace = True) 
Freq_df.head()

reset_index方法的使用还是比较频繁的,它可以非常方便地将行标 签转换为数据框的变量。在如上代码中,将reset_index方法中的inplace参数设置为True,表示直接对原始数据集进行操作,响到原数据集的 变化,否则返回的只是变化预览,并不会改变原数据集。

四、字符与日期数据的处理

本节会介绍有关 日期型数据的处理,比方说,如何从日期型变量中取出年份、月份、星 期几等,如何计算两个日期间的时间差。

下面不啰嗦,直接举例说明:数据集查看2

 

 下面演示一些常用的操作:

#数据读入
df = pd.read_excel('data.xlsx')
#各变量数据类型
df.dtypes
#将出生日期变量转换为日期型
df.出生日期 = pd.to_datetime (df.出生日期,format = '%Y /%m/%d')
#将手机号转换为字符串
df .电话号码 = df.电话号码.astype ( 'str')
#新增年龄和工龄两列
df [ '年龄'] = pd.datetime.today ().year - df.出生日期.dt.year
df [ '工龄'] = pd.datetime.today ().year - df.工作时间.dt.year
#取出邮箱的域名
df [ '邮箱域名'] = df.邮箱.apply(func = lambda x : x.split ('@') [1])
#将手机号中间四位隐藏起来
df.电话号码 = df.电话号码.apply(func = lambda x : x.replace(x[3:7],'**** '))
#去除邮箱变量
df.drop([ '邮箱' ], axis = 1, inplace = True)
df.head()

 常用的日期时间处理“方法”

接下来,挑选几个日期处理 方法 用以举例说明:
#常用日期处理方法
dates = pd.to_datetime (pd.Series(['1989-8-18 13:14:55','1995-2-16']),format='%Y-%m-%d %H:%M:%S')
print('返回日期值:\n ',dates.dt.date)
print('返回季度:\n',dates.dt.quarter)
print('返回几点钟:\n',dates.dt.hour)
print('返回年中的天:\n',dates.dt.dayofyear)
print ('返回年中的周:\n',dates.dt .weekofyear)
#print('返回星期几的名称:\n',dates.dt.weekday_name)
print('返回月份的天数: \n ',dates.dt.days_in_month)

五、常用的数据清洗方法

       在数据处理过程中,一般都需要进行数据的清洗工作,如数据集是 否存在重复、是否存在缺失、数据是否具有完整性和一致性、数据中是 否存在异常值等。当发现数据中存在如上可能的问题时,都需要有针对 性地处理,本节将重点介绍如何识别和处理重复观测、缺失值和异常值。

1、重复观测处理

2、缺失值处理

3、异常值处理

六、数据子集的获取

       有时数据读入后并不是对整体数据进行分析,而是数据中的部分子 集,例如,对于地铁乘客量可能只关心某些时间段的流量、对于商品的 交易可能只需要分析某些颜色的价格变动、对于医疗诊断数据可能只对 某个年龄段的人群感兴趣等。所以,该如何根据特定的条件实现数据子 集的获取将是本节的主要内容。

#构造数据集
df1 = pd.DataFrame ( {'name':[ '张三','李四','王二','丁一','李五'],
'gender':['男','女','女','女','男'],
'age':[23,26,22,25,27]},columns = ['name' , 'gender' , 'age'])
df1
#取出数据集的中间三行{即所有女性),并且返回姓名和年龄两列
#df1.iloc[1:4, [0,2]]
#df1.loc[ 1 : 3,['name','age']]
#df1.ix[1:3,[0.2]]

如上结果所示,如果原始数据的行号与行标签(名称)一致, iloc、locix三种方法都可以取出满足条件的数据子集。所不同的是, iloc运用了索引的思想,故中间三行的表示必须用1:4,因为切片索引取 不到上限,同时,姓名和年龄两列也必须用数值索引表示;loc是指获 取行或列的标签(名称),由于该数据集的行标签与行号一致,所以 1:3就表示对应的3个行名称,而姓名和年龄两列的获取就不能使用数值 索引了,只能写入具体的变量名称;ix则混合了ilocloc的优点,如果 数据集的行标签与行号一致,则ix对观测行的筛选与loc的效果一样,但 是ix对变量名的筛选既可以使用对应的列号(如代码所示),也可以使 用具体的变量名称。

# 将员工的姓名用作行标签 
df2 = df1.set_index('name')
df2 # 取出数据集的中间三行 df2.iloc[1:4,:] 
df2.loc[['李四','王二','丁一'],:] 
df2.ix[1:4,:]
很显然,在实际的学习和工作中,观测行的筛选很少是通过写入具 体的行索引或行标签,而是对某些列做条件筛选,进而获得目标数据。 例如,在上面的df1数据集中,如何返回所有男性的姓名和年龄,代码 如下:
# df1.iloc[df1.gender == '男',] 
df1.loc[df1.gender == '男',['name','age']] 
df1.ix[df1.gender == '男',['name','age']]

        综上所述,ix方法几乎可以实现所有情况中数据子集的获取,是 iloc和loc两种方法的优点合成体,而且对于行号与行名称一致的数据集 来说(如df1数据集),名称索引的优先级在位置索引之前(如本节第 一段代码中的df1.ix[1:3,[0,2]])。

七、透视表功能

如果这样的汇总过程不是在Excel中,而是在Python中,该如何实现呢?Pandas模块提供了实现透视表功能的pivot_table函数,该函数简单易用,与Excel的作思想完全一致,相信读者一定可以快速掌握函数 的用法及参数含义。接下来向读者介绍一下有关该函数的参数含义:

pd.pivot_table(data,values=None,index=None,columns=None,
aggfunc='mean', fill_value=None,margins=False,dropna=True, margins_name= 'Al1')

data指定需要构造透视表的数据集。

values指定需要拉入数值框的字段列表。

index指定需要拉入行标签框的字段列表。

columns指定需要拉入列标签框的字段列表。

aggfunc指定数值的统计函数,默认为统计均值,也可以指定numpy模块中的其他统计函数。

fill_value指定一个标量,用于填充缺失值。

marginsbool类型参数,是否需要显示行或列的总计值,默认为False。

dropnabool类型参数,是否需要删除整列为缺失的字段,默认为True

margins_name指定行或列的总计名称,默认为All

为了说明该函数的灵活功能,这里以上面的珠宝数据为例,重现 Excel制作成的透视表。首先来尝试一下单个分组变量的均值统计,具 体代码如下:

# 数据读取 diamonds = pd.read_table(r'diamonds.csv', sep = ',') 
# 单个分组变量的均值统计 
pd.pivot_table(data = diamonds, index = 'color', values = 'price', margins = True,margins_name = '总计')

如上结果所示就是基于单个分组变量color的汇总统计(price的均 值),返回结果属于Pandas模块中的序列类型,该结果与Excel形成的透 视表完全一致。接下来看看如何构造两个分组变量的列联表,代码如下 所示:

#两个分组变量的列联表
#导入numpy模块
import numpy as np
pd.pivot_table (data = diamonds,index m 'clarity', columns = 'cut ',values = 'carat',
aggfunc - np.size,margins = True,margins_name - '总计')

八、表之间的合并与连接

Pandas模块同样提供了关于多表之间的合并和连接操作函数,分别 是concat函数和merge函数,首先介绍一下这两个函数的用法和重要参数 含义。

(1)合并函数 concat
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False)

objs指定需要合并的对象,可以是序列、数据框或面板数据构 成的列表。

axis指定数据合并的轴,默认为0,表示合并多个数据的行,如 果为1,就表示合并多个数据的列。

join指定合并的方式,默认为outer,表示合并所有数据,如果 改为inner,表示合并公共部分的数据。

join_axes合并数据后,指定保留的数据轴。

ignore_indexbool类型的参数,表示是否忽略原数据集的索引, 默认为False,如果设为True,就表示忽略原索引并生成新索引。

keys为合并后的数据添加新索引,用于区分各个数据部分。

#构造数据集df1和 df2
df1 = pd.DataFrame ( { 'name' :[ '张三','李四','王二'], 'age' : [21,25,22],
'gender" :['男','女·,'男']})
df2 = pd.DataFrame ( { 'name' : [ '丁一', '赵五'],'age' :[23,22],'gender ' : [ '女', '女']})
#数据集的纵向合并
pd.concat ([df1, df2] , keys =['df1', 'df2 '])
#并如果df2数据集中的“姓名变量为Name”
df2 = pd.DataFrame ( { 'Name ' : [ '丁一','赵五'],'age ' : [23,22],'gender ' : ['女', '女'] )
#数据集的纵向合并
pd.concat([df1,df2])
(2)连接函数 merge
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False)

left指定需要连接的主表。

right指定需要连接的辅表。

how指定连接方式,默认为inner内连,还有其他选项,如左连 left、右连right和外连outer

on指定连接两张表的共同字段。left_on:指定主表中需要连接的共同字段。

right_on指定辅表中需要连接的共同字段。

left_indexbool类型参数,是否将主表中的行索引用作表连接的 共同字段,默认为False

right_indexbool类型参数,是否将辅表中的行索引用作表连接 的共同字段,默认为False

sortbool类型参数,是否对连接后的数据按照共同字段排序, 默认为False

suffixes如果数据连接的结果中存在重叠的变量名,则使用各自 的前缀进行区分。

九、分组聚合操作

df=pd.DataFrame({'A':['foo','bar','foo','bar','foo','bar','foo','foo'],'B':['one','one','two','three','two','two','one','three'],'C':np.random.randn(8),'D':np.random.randn(8)})
df.groupby('A').sum()
df.groupby(['A','B']).sum()

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿童学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值