目录
1. 数据结构简介
1.1 Series的创建
1.2 DataFrame的创建
2. 数据索引index
2.1 通过索引值或索引标签获取数据
2.2 自动化对齐
3. 利用pandas查询数据
4. 利用pandas的DataFrames进行统计分析
5. 利用pandas实现SQL操作
6. 利用pandas进行缺失值的处理
7. 利用pandas实现Excel的数据透视表功能
8. 多层索引的使用
【此文旨在个人学习过程中知识点回顾,希望对大家也有帮助】
B站同步视频bilibili.com/video/av63245020
一、数据结构介绍
在pandas中有两类非常重要的数据结构,即序列Series和数据框DataFrame。Series类似于numpy中的一维数组,除了通用一维数组的函数和方法,而且可通过索引标签的方式获取数据,还具有索引的自动对齐功能;DataFrame类似于numpy中的二维数组,同样可以通用numpy数组的函数和方法,且具有其他应用后续详聊。
1.1Series的创建
序列的创建有其他三种方式:
1)通过一维数组创建序列
import numpy as np
import pandas as pd
a = np.arange(10)
print(a, type(a))
a1 = pd.Series(a) #利用a得到的一维数组直接创建序列
print(a1, type(a1))
#自行运行观察结果
2)通过字典方式创建序列
a = {'a':10,'b':20,'c':30,'d':40,'e':50}
print(a, type(a))
a_Series = pd.Series(a)
print(a_Series, type(a_Series))
#自行运行观察结果
3)通过DataFrame中的某一行或某一列创建
此方法不展开,详细可百度
1.2DataFrame数据框的创建——三种方法
1)通过二维数组是创建
a = np.arange(np.arange(12)).reshape(3, 4)
print(a, type(a))
df1 = pd.DataFrame(a)
print(df1, type(df1))
#自行运行观察结果
2)通过字典方式创建
#字典列表方式
dic2 = {'a':[1,2,3,4],'b':[5,6,7,8],'c':[9,10,11,12],'d':[13,14,15,16]}
print(dic2)
print(type(dic2))
df2 = pd.DataFrame(dic2) ## 创建方式
print(df2)
print(type(df2))
#嵌套字典方式
dic3 = {'one':{'a':1,'b':2,'c':3,'d':4},'two':{'a':5,'b':6,'c':7,'d':8},'three':{'a':9,'b':10,'c':11,'d':12}}
print(dic3)
print(type(dic3))
df3 = pd.DataFrame(dic3)
print(df3)
print(type(df3))
#自行运行观察结果
3)通过数据框的方式创建数据框
df4 = df3[['one','three']]
print(df4, type(df4))
s3 = df3['one']
print(s3, type(s3))
二、数据索引丨index
细致的朋友可能会发现一个现象,无论序列、数据框,对象的左边总有一个非原始数据对象,这就是索引。序列或数据框的索引有两大用处,一个事通过索引值或索引标签获取数据,另一个是通过索引,可以使序列或数据框的数据自动化对齐。
2.1通过索引或索引标签获取数据
s4 = pd.Series(np.array([1,1,2,3,5,8]))
print(s4)
如果不给序列一个指定的索引值,则序列自动生成一个从0开始的自增索引。可以通过index查看索引。
print(s4.index)
创建自定义索引值:
s4.index = ['a','b','c','d','e','f']
print(s4)
数据有了索引值或索引标签就可以利用后去数据:
print('s4[3]:',s4[3])
print('s4[e]:',s4['e'])
print('s4[1,3,5]:',s4[[1,3,5]])
print("s4[['a','b','d','f']]:",s4[['a','b','d','f']])
print('s4[:4]:',s4[:4])
print("s4['c':]:",s4['c':])
print("s4['b':'e']:",s4['b':'e'])
#自行操作观察结果
千万注意:如果通过索引标签获取数据的话,末端标签所对应的值是可以返回的!在一维数组中就无法通过标签获取数据,这也是序列不同于一维数组的一个方面。
2.2自动化对齐
若有两个序列,对其进行算数运算,这是索引就体现了价值——自动化对其。
s5 = pd.Series(np.array([10,15,20,30,55,80]),index = ['a','b','c','d','e','f'])
print(s5)
s6 = pd.Series(np.array([12,11,13,15,14,16]),index = ['a','c','g','b','d','f'])
print(s6)
print(s5+s6)
print(s5/s6)
由于s5、s6中存在非对应索引,故结果存在NaN。注意,这里的算数结果就实现了序列索引的自动对齐。对于数据框不仅自动对齐行,也会自动对齐列(变量名)。
数据框中同样存在索引,且数据框是二维数据组的推广,故其不仅有行索引又有列索引,关于数据框中的索引要比序列强大很多。
三、利用pandas 查询数据
这里的查询数据相当于R语言的subset功能,可以通过布尔索引有针对的选取元数据的子集、指定行&列等。
import pandas as ps
stu_dic = {'Age':[14,13,13,14,14,12,12,15,13,12,11,14,12,15,16,12,15,11,15],
'Height':[69,56.5,65.3,62.8,63.5,57.3,59.8,62.5,62.5,59,51.3,64.3,56.3,66.5,72,64.8,67,57.5,66.5],
'Name':['Alfred','Alice','Barbara','Carol','Henry','James','Jane','Janet','Jeffrey','John','Joyce','Judy','Louise','Marry','Philip','Robert','Ronald','Thomas','Willam'],
'Sex':['M','F','F','F','M','M','F','F','M','M','F','F','F','F','M','M','M','M','M'],
'Weight':[112.5,84,98,102.5,102.5,83,84.5,112.5,84,99.5,50.5,90,77,112,150,128,133,85,112]}
student = pd.DataFrame(stu_dic) #导入数据创建数据框
print(student.head()) #查询数据前5列
print(student.tail()) #查询数据后5列(默认)
查询指定行
print(student.loc[[0,2,4,5,7]]) #这里的loc索引标签函数必须是中括号[]
查询指定列
print(student[['Name','Height','Weight']].head()) #如果多个列的话,必须使用双重中括号[]
#方法2
print(student.loc[:,['Name','Height','Weight']].head())
查询12岁以上的女生信息
student[(条件1) & (条件2)]
print(student[(student['Sex']=='F') & (student['Age']>12)])
自己写出下面这条需求
查询出所有12岁以上女生姓名、身高和体重?
student[(student['Sex']=='F') & (student['Age']>12)][['Name','Height','Weight']]
注意:如果是多个条件的查询,必须使用&(and)或者丨(or)的两端条件用括号括起来。
四、利用pandas 的DataFrame进行统计分析
np.random.seed(1234)
d1 = pd.Series(2*np.random.normal(size = 100)+3)
d2 = np.random.f(2,4,size = 100)
d3 = np.random.randint(1,100,size = 100)
print('非空元素计算: ', d1.count()) #非空元素计算
print('最小值: ', d1.min()) #最小值
print('最大值: ', d1.max()) #最大值
print('最小值的位置: ', d1.idxmin()) #最小值的位置,类似于R中的which.min函数
print('最大值的位置: ', d1.idxmax()) #最大值的位置,类似于R中的which.max函数
print('10%分位数: ', d1.quantile(0.1)) #10%分位数
print('求和: ', d1.sum()) #求和
print('均值: ', d1.mean()) #均值
print('中位数: ', d1.median()) #中位数
print('众数: ', d1.mode()) #众数
print('方差: ', d1.var()) #方差
print('标准差: ', d1.std()) #标准差
print('平均绝对偏差: ', d1.mad()) #平均绝对偏差
print('偏度: ', d1.skew()) #偏度
print('峰度: ', d1.kurt()) #峰度
print('描述性统计指标: ', d1.describe()) #一次性输出多个描述性统计指标
########## 自行操作观察结果,加深记忆 ###############
必须注意的是,descirbe方法只能针对序列或数据框,一维数组是没有这个方法的
定义一个函数将描述性统计指标汇总到一起:
def stats(x):
return pd.Series([x.count(),x.min(),x.idxmin(),x.quantile(.25),x.median(),x.quantile(.75),
x.mean(),x.max(),x.idxmax(),x.mad(),x.var(),x.std(),x.skew(),x.kurt()],
index = ['Count','Min','Whicn_Min','Q1','Median','Q3','Mean','Max',
'Which_Max','Mad','Var','Std','Skew','Kurt'])
print(stats(d1))
在实际工作中,可能处理一些数据型数据框,将函数应用到数据框中的每一列,可以使用apply函数,将之前创建的d1\d2\d3数据构建为数据框:
df = pd.DataFrame(np.array([d1,d2,d3]).T,columns = ['x1','x2','x3']) #.T进行转置
print(df.head())
print(df.apply(stats))
#输出效果很神奇
对于离散型数据,需要统计离散变量的观测数、唯一值个数、众数水平及个数。使用descirbe方法便可实现:
print(student['Sex'].describe())
count 19 unique 2 top M freq 10 Name: Sex, dtype: object
连续变量的相关系数(corr)和协方差矩阵(cov)的求解
print(df.corr())
print(df.corr('spearman'))
#关于相关系数的计算可以调用pearson方法或kendell方法或spearman方法,默认使用pearson方法。
如果只想关注某一个变量与其余变量的相关系数的话,可以使用corrwith,如下方只关心x1与其余变量的相关系数:
print(df.corrwith(df['x1']))
数值型变量间的协方差矩阵
print(df.cov())
五、利用pandas实现SQL操作
增删改查!!!
#创建新数据框student2
dic = {'Name':['LiuShunxiang','Zhangshan'],'Sex':['M','F'],'Age':[27,23],'Height':[165.7,167.2],'Weight':[61,63]}
student2 = pd.DataFrame(dic)
print(student2)
增:添加新行或新列
将student2中的数据新增到student中,通过concat函数实现:
student3 = pd.concat([student, student2])
print(student3)
在数据库中union必须要求两张表的顺序一致,而这里concat函数可以自动对齐两个数据框数据。
新增列:
print(pd.DataFrame(student2, columns = ['Age','Height','Name','Sex','Weight','Score']))
新增的列没有赋值,则会NaN。
删:删除表、观测行和变量列
del student2 #直接删除
print(student.drop([0,1,3,6])) # 删除指定行
print(student[student['Age']>14]) #删除满足Age中大于14的数据行
print(student.drop(['Height','Weight'],axis=1).head()) #删除指定列
发现不论是删除列还是行,都可以通过drop方法实现,只需要设定好删除的轴即可,即调整drop方法中的阿西斯参数。默认该参数为0,表示删除行观测,参数1表示删除列变量。
改:修改原始记录的值
例如发现student3中姓名为LiuShunxiang的学生身高错了,应该是173,如何改?
student3.loc[syudent3['Name'] == 'LiuShuanxiang','Height'] = 173
print(student3)
print(syudent3[syudent3['Name'] == 'LiuShunxiang'][['Name','Height']]) # 仅获取指定索引的某一数据
查:有关数据查询部分,上面已经介绍过了
重点来了
聚合:pandas模块中可以通过groupby()函数实现数据的聚合操作
根据性别分组,计算各组别中学生身高he体重的均值:
print(student.groupby('Sex').mean())
如果不对源数据做限制的话,聚合数据会自动选择数值型数据进行聚合计算。如果不想对年龄计算平均值的话就需要剔除改变量:
print(student.drop('Age',axis=1).groupby('Sex').mean())
groupby还可以使用多个分组变量,例如根据年龄和性别分组,计算身高和体重的平均值:
print(student.groupby(['Age','Sex']).std()) #注意这里的中括号
当然也可以对每个分组进行多个统计量计算:
print(student.drop('Age',axis=1).groupby('Sex').agg([np.mean,np.median]))
排序:
排序在日常工作中使用较多,可以通过sort_index 和 sort_values实现对序列和数据框的排序工作:
Data = pd.Series(np.array(np.random.randint(1,20,10)))
print(Data)
print(Data.sort_index())
print(Data.sort_values(ascending=False)) #False为降序,True 为升序
在数据框中一般都是按值排序:
print(student.sort_values(by = ['Age','Height']))
多表链接:
多表连接是非常常见的数据库操作,连接分内链接和外连接,在数据库中通过join关键字实现,pandas我比较建议使用merge函数实现数据的各种连接操作。如下构造一张学生的成绩表:
dic2 = {'Name':['Alfred','Alice','Barbara','Carol','Henry','Jeffrey','Judy','Philip','Robert','Willam'],
'Score':[88,76,89,67,79,90,92,86,73,77]}
score = pd.DataFrame(dic2)
print(score)
将student与score进行关联:
stu_score1 = pd.merge(student, score,on = 'Name')
print(stu_score1)
注意:merge函数默认情况下实现两个表的内连接,即返回两张表中共有部分。通过how参数设置连接方式,left为左连接,right为右连接,outer为外连接。
stu_score3 = pd.merge(student, score, on = 'Name', how = 'left')
print(stu_score3)
左连接实现的是保留student中的数据,将score与之匹配,能匹配多少算多少,匹配不上的显示NaN。
六、利用pandas进行缺失值处理
常用三种方法,删除法,填补法,插值法。
删除法:当数据中某个变量大部分都是缺失值,可以考虑将其删除;当缺失值是随机分布的,且缺失值并不是很多,可以选择删除这些缺失值的观测。
替补法:对于连续型变量,若变量的分布近似或就是正态分布的话,可以用均值替代那些缺失值‘如果变量是有偏的,可以使用中位数来替代,对于离散型数据一般使用众数来替换缺失的观测。
插补法:插补法基于蒙特卡洛模拟法,结合线性模型、广义线性模型和决策树等方法计算出来的预测值替换缺失值。
简单的删除法和替补法:
s = stu_score3['Score']
print(s)
上面显示的是一组含有缺失值的序列,结合sum和isnull函数来检测数据中含有多少缺失值:
print(sum(pd.isnull(s))) #显示9个
直接删除缺失值:
print(s.dropna())
默认dropna会删除含有缺失值的行,试一下:
df = pd.DataFrame([[1,1,2],[3,5,np.nan],[13,21,34],[55,np.nan,10],[np.nan,np.nan,np.nan],[np.nan,1,2]],columns=('x1','x2','x3'))
print(df)
print(df.dropna())
返回结果表明,数据中只要含有NaN,该行就会被删掉。若使用参数how='all',则表明只删除所有行为缺失值的观测;使用一个常量填补缺失值,可以使用fillna实现简单的填补:
1)用0填补所有缺失值
print(df.fillna(0))
2)采用前项、后项填补
print(df.fillna(method='ffill'))
print(df.fillna(method='bfill'))
#如果前项或后项无值,则继续NaN
3)使用常量填补不同的列
print(df.fillna({'x1':1,'x2':2,'x3':3})) # 注意使用{ }
很显然使用各项的median、mode、mean填充更加合理一点。
七、利用pandas实现Excel的数据透视表功能
pivo_table(data, values=None,
index = None,
columns = None,
aggfunc = 'mean',
fill_values = None,
margins = False,
dropna = True,
margind_name = 'All')
data:需要进行数据透视操作的数据框
values:指定需要聚合的字段
index:制定某些原始变量作为行索引
columns:指定那些离散的分组变量
aggfunc:指定相应的聚合函数
margins:是否进行行列的汇总,默认不汇总
dropna:某人所有观测为确实的列
margins_name:默认行汇总和列汇总的名称为All
利用pivot_table函数的用法:对一组变量(Sex),一个数据变量(Height)进行统计汇总
Table1 = pd.pivot_table(student, values=['Height'], columns=['Sex'])
print(Table1)
对一个分组变量(Sex),两个数值变量(Height,Weight)进行统计汇总
Table2 = pd.pivot_table(student, values=['Height','Weight'], columns=['Sex'])
print(Table2)
对两个分组变量(Sex,Age),两个数值变量(Height,Weight)进行汇总
Table3 = pd.pivot_table(student, values=['Height','Weight'],columns=['Sex','Age'])
print(Table3) #打印出来可能不太好看,可以进行非堆叠操作
Table3 = pd.pivot_table(student, values=['Height','Weight'],columns=['Sex','Age']).unstack()
print(Table3)
使用多个聚合函数
Table5 = pd.pivot_table(student, values=['Height','Weight'],columns=['Sex'],aggfunc=[np.mean,np.median,np.std])
print(Table5)
有关更多数据透视表的操作,可参考《Pandas透视表(pivot_table)详解》一文,链接地址:http://python.jobbole.com/81212/ (链接时灵时不灵)
八、多层索引的使用
最后我们再来讲讲pandas中的一个重要功能,那就是多层索引。在序列中它可以实现在一个轴上拥有多个索引,就类似于Excel中常见的这种形式:
pandas可以帮我们实现用低维度形式处理高维数数据,这里举个例子:
#Series的层次化索引,索引是一个二维数组,相当于两个索引决定一个值
#有点类似于DataFrame的行索引和列索引
s = pd.Series(np.arange(1,10),index=[["a","a","a","b","b","c","c","d","d"],[1,2,3,1,2,3,1,2,3]])
print(s)
print(s.index)
索引操作
#选取外层索引为a的数据
print(s['a'])
#选取外层索引为a和内层索引为1的数据
print(s['a'],1)
#选取外层索引为a和内层索引为1,3的数据
print(s['a'][[1,3]])
#层次化索引的切片,包括右端的额索引
print(s[['a','c']])
print(s['b':'d'])
#通过unstack方法可以讲Series变成一个DataFrame
#数据类型和数据的输出结构都变成了DataFrame,对于不存在的部分使用NaN填充
print(s.unstack())
### 自行原型观察结果 ### 只看学不会,关键还是练
DataFrame的层次化索引
#创建新的DataFrame
data = pd.DataFrame(np.random.randint(0,150,size=(8,12)),
columns = pd.MultiIndex.from_product([['模拟考','正式考'],
['数学','语文','英语','物理','化学','生物']]),
index = pd.MultiIndex.from_product([['期中','期末'],
['雷军','李斌'],
['测试一','测试二']]))
data # 观察data
索引操作
data['模拟考'][['语文','数学']]
####
print(data.loc['期中','雷军','测试一']['模拟考','数学'])
print(data.loc['期中','雷军','测试一'])
print(data.iloc[0]) #结果与上边的一样
#
data['正式考']
掌握了pandas这8个主要的应用方法就可以灵活的解决很多工作中的数据处理、统计分析等任务。
最近准备将我之前写的数据分析报告,数据源,以及python分析源代码整理发布到Pandas中文社区。此外还将在bilibili将操作的数据分析项目用视频的方式讲解出来,一方面加深自己的记忆提高熟练度,另一方面个希望对大家也有帮助。
有关更多的pandas介绍,可参考Pandas中文文档。