pandas入门
pandas是贯穿整个数据分析过程的重要工具,它包含的数据结构和数据处理工具的设计使得在Python中进行数据清洗和分析非常快捷。pandas经常是和其他数值计算工具,比如NumPy和SciPy,以及数据可视化工具比如matplotlib一起使用的。pandas支持大部分NumPy语言风格的数组计算,尤其是数组函数以及没有for循环的各种数据处理。
尽管pandas采用了很多风格的NumPy的代码风格,但最大的不同在于pandas是用来处理表格型或异质型数据的,而NumPy则更适合用来处理同质型数值类数组数据。
pandas在2010年成为了开源项目,至今已经有了超过800多位代码贡献者,至于pandas这个名字,和动物熊猫panda是没有任何关系的😆,pandas是Python data analysis的缩写,同时也衍生自计量经济学术语panel data,通过这个名字就可以知道,pandas就是天生用来进行数据分析的。
import pandas as pd
from pandas import Series,DataFrame
1 pandas数据结构介绍
pandas有两个常用的工具数据结构:Series和DataFrame。
1.1 Series
Series是一种一维的数组型对象,它包含了一个值序列(类似于NumPy中的类型),并且包含了数据标签,称为索引(index)。最简单的序列可以仅仅由一个数组形成。
obj=pd.Series([4,7,-5,3])
obj
#0 4
#1 7
#2 -5
#3 3
#dtype: int64
obj.values
#array([ 4, 7, -5, 3], dtype=int64)
obj.index #和range(4)类似
#RangeIndex(start=0, stop=4, step=1)
obj2=pd.Series([4,7,-5,3],index=['d','b','a','c'])
obj2
#d 4
#b 7
#a -5
#c 3
#dtype: int64
obj2.index
#Index(['d', 'b', 'a', 'c'], dtype='object')
obj2['b']
#7
obj2['d']=6
obj2[['c','a','d']]
#c 3
#a -5
#d 6
#dtype: int64
上面的例子中,[’c’,’a’,’d’]
包含的不是数字而是字符串,作为索引列表。
使用NumPy的函数,比如使用布尔值数组进行过滤,与标量相乘,或是应用数学函数,这些操作将保存索引值连接:
obj2[obj2>0]
#d 6
#b 7
#c 3
#dtype: int64
obj2>0
#d True
#b True
#a False
#c True
#dtype: bool
np.exp(obj2)
#d 403.428793
#b 1096.633158
#a 0.006738
#c 20.085537
#dtype: float64
从另一个角度理解Series,可以认为它是固定且有序的字典,因为他将索引值和数据值按位置配对,在你可能用字典的上下文中,也可以使用Series:
sdata={'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000}
obj3=pd.Series(sdata)
obj3
#Ohio 35000
#Texas 71000
#Oregon 16000
#Utah 5000
#dtype: int64
states=['Califorlia','Ohio','Oregon','Texas']
obj3=pd.Series(sdata,index=states)
obj3
#Califorlia NaN
#Ohio 35000.0
#Oregon 16000.0
#Texas 71000.0
#dtype: float64
pd.isnull(obj3)
#Califorlia True
#Ohio False
#Oregon False
#Texas False
#dtype: bool
1.2 DataFrame
DataFrame表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引。它可以被视为一个共享相同索引的Series字典。在DataFrame中,数据被存储为一个以上的二维块,而不是列表、字典或其他一维数组的集合。DataFram内部的精确细节不在本书的讨论范围。
通常来说DataFrame可以利用包含等长度列表或者NumPy数组的字典来形成。
DataFrame会自动为Series分配索引,并会将列按顺序排列。
data={'state':['Ohio','Ohio','Ohio','Nevada','Nevada','Nevada'],
'year':[2000,2001,2002,2001,2002,2003],
'pop':[1.5,1.7,3.6,2.4,2.9,3.2]
}
frame=pd.DataFrame(data,columns=['year','state','pop','debt'],index=['one','two','three','four','five','six'])
val=pd.Series([-1.2,-1.5,-1.7],index=['two','four','five'])
frame['debt']=val
frame['eastern']=frame.state=='Ohio'
del方法可以用来移除已有的列,loc方法可以通过索引选取指定的行。
值得注意的是,从DataFrame中选取的列是数据的视图,而不是拷贝。因此,对Series的修改会映射到DataFrame中。如果需要复制,则应当显式地使用Series的copy方法。
另一种常用的数据形式是包含字典的嵌套字典
pop={'Nevada':{2001:2.4,2002:2.9},'Ohio':{2000:1.5,2001:1.7,2002:3.6}}
frame3=pd.DataFrame(pop)
frame3
如果嵌套字典被赋值给DataFrame,pandas会将字典的键作为列,内部字典的键作为行,如下
frame3.T
和Series一样,DataFrame也可以输入index来主动的排序,可以通过name属性给指定的对象命名,自行尝试一下。
DataFrame构造函数的有效输入
2Dndarray | 数据的矩阵、行列坐标标签是可选参数 |
---|---|
数组、列表和元组构成的字典 | 序列长度需要一致 |
NumPy结构化/记录化数组 | 与数组构成的字典一致 |
Series构成的字典 | 每个值成为一列 |
字典构成的字典 | |
字典或Series构成的列表 | |
列表和元组构成的列表 | 与2Dndarray的情况一致 |
其他DataFrame NumPy MaskedArray |
1.3索引对象
pandas中的索引对象适用于存储轴标签和其他的元数据的。在构造Series或DataFrame时,你所使用的任意数组或标签序列都可以在内部转换为索引对象。
obj=pd.Series(range(3),index=['a','b','c'])
index=obj.index
#Index(['a', 'b', 'c'], dtype='object')
index[1:]
#Index(['b', 'c'], dtype='object')
index[1]='d'
#TypeError: Index does not support mutable operations
索引对象是不可变的,因此用户是无法修改索引对象的。
索引对象的方法和属性:
append | 将额外的索引对象粘贴到原索引,产生一个新的索引 |
---|---|
difference | 计算两个索引的差集 |
intersection | ···交集 |
union | ···并集 |
isin | 计算每个值是否在传值容器中的布尔数组 |
delete | 将位置i的元素删除,并产生新的索引 |
drop | 根据传参删除指定索引值,并产生新的索引 |
insert | 在位置i处插入元素,并产生新的索引 |
is_monotonic | 如果索引序列递增则返回True |
is_unique | 如果索引序列唯一则返回True |
unique | 计算索引的唯一值序列 |
2基本功能
2.1重建索引
reindex时pandas对象的重要方法,该方法用于创建一个符合新索引的新对象。
obj=pd.Series([4.5,7.2,-5.3,3.6],index=['d','b','a','c'])
obj
obj2=obj.reindex(['a','b','c','d','e'])
obj2
调用reindex方法的时候,会将数据按照新索引进行排列,如果某个索引值不存在,则会引入缺失值。
对于顺序数据比如序列,在重建索引时可能会需要进行插值或填值,method可选参数允许我们使用诸如ffill等方法在重建索引时·插值,ffill方法会将值前向填充。
obj3=pd.Series(['Blue','Purple','yellow'],index=[0,2,4])
obj3
obj3.reindex(range(6),method='ffill')
#0 Blue
#1 Blue
#2 Purple
#3 Purple
#4 yellow
#5 yellow
#dtype: object
在DataFrame中,reindex可以改变行索引、列索引,也可以同时改变二者。
frame=pd.DataFrame(np.arange(9).reshape((3,3)),index=['a','b','c'],columns=['ohio','texas','california'])
frame
frame2=frame.reindex(['a','b','c','d'])
states=['texas','ohio','utah','california']
frame.reindex(columns=states)
也可以使用loc进行更为简洁的标签索引。
reindex方法的参数
method | 插值方式,ffill向前填充,bfill向后填充 |
---|---|
limit | 填充时,所需填充的最大尺寸间隙(以元素数量) |
fill_value | 通过重新索引引入缺失数据时,使用的替代值 |
tolerance | 填充时,所需填充的不精确匹配下的最大尺寸间隙,(以绝对数字距离) |
level | 匹配MultiIndex级别的简单索引,否则选择子集 |
copy | 如果True,即使新索隐等于旧索引,也总是复制底层数据,如果为False,则在索引项同时不要复制数据。 |
2.2轴向上删除条目
如果你已经拥有了索引数组或不含条目的列表,在轴向上删除一个或更多的条目就非常容易,但这样需要一些数据操作和集合逻辑,drop方法会返回一个含有指示值或轴向上删除值得新对象,如下:
obj=pd.Series(np.arange(5.),index=['a','b','c','d','e'])
obj
new_obj=obj.drop('c')
obj.drop(['d','c'])
在DataFrame中,索引值可以从轴向上删除:
data=pd.DataFrame(np.arange(16).reshape((4,4)),index=['ohio','colorada','utah','newyork'],
columns=['one','two','three','four'])
data
data.drop(['colorada','ohio'])
通过传递axis=1或者axis=’columns’来从列中删除值。
2.3索引、选择与过滤
Series的索引(obj[…])与NumPy数组索引的功能类似,只不过Series的索引值可以不仅仅是整数。
obj=pd.Series(np.arange(4.),index=['a','b','c','d'])
obj['b']
#1
obj[2:4]
#c 2.0
#d 3.0
#dtype: float64
obj[obj<2]
#a 0.0
#b 1.0
#dtype: float64
obj['b':'d']
#b 1.0
#c 2.0
#d 3.0
#dtype: float64
使用以上的方法时,设值会修改Series相应的部分:
obj['b':'c']=10
data=pd.DataFrame(np.arange(16).reshape((4,4)),
index=['ohio','colorado','utah','newyork'],
columns=['one','two','three','four']
)
data[data['three']>5]
如上,便是使用布尔值数组来进行索引。
2.3.1使用loc和iloc选择数据
针对DataFrame在行上的标签索引,可以使用轴标签(loc)或整数标签(iloc)以NumPy风格的语法从DataFrame中选出数组行和列的子集。
data=pd.DataFrame(np.arange(16).reshape((4,4)),
index=['ohio','colorado','utah','newyork'],
columns=['one','two','three','four']
)
data[data['three']>5]
data.loc['colorado',['two','three']]
data.loc[['ohio','colorado'],['two','three']]
data.iloc[2,[2,3,1]]
2.4整数索引
对pandas对象使用整数索引和python内建数据结构进行索引有些不同。
因为无法确定这个是标签索引或位置索引。
所以为了保持一致性,如果你有一个包含整数轴索引,数据选择时请始终使用标签索引,为了更精确的处理,可以使用loc(用于标签)或iloc(用于整数)。
2.5算术和数据对齐
不同索引的对象之间的算术行为是pandas的一个重要的特性。当你将对象相加时,如果存在某个索引对不同,则返回结果的索引将时索引对的并集。
在没有交叠的标签位置,内部数据对齐会产生缺失值,只有重叠的标签对应值会相加。
DataFrame上也是这样的。
2.5.1使用填充值的算术方法
使用add方法的同时输入参数fil_value就可以设置相加非交集的默认值。
add、radd | 加法+ |
---|---|
sub、rsub | 减法- |
div、rdiv | 除法/ |
floordiv、rfloordiv | 整除// |
mul、rmul | 乘法* |
pow、rpow | 幂次方** |
2.5.2DataFrame和Series间的操作
DataFrame和Series之间的操作类似于NumPy中不同维度数组间的操作。
arr=np.arange(12).reshape((3,4))
arr
#array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
arr-arr[0]
#array([[0, 0, 0, 0],
# [4, 4, 4, 4],
# [8, 8, 8, 8]])
以上是numpy多维数组之间的操作。
frame=pd.DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['utah','ohio','texas','oregon'])
series=frame.iloc[0]
frame-series
2.6函数应用和映射
NumPy的通用函数对pandas对象也有效:
frame=pd.DataFrame(np.random.randn(4,3),columns=list('bde'),index=['utah','ohio','texas','oregon'])
frame
np.abs(frame)
另一个常用的操作是将函数应用到一行或一列的一维数组上,DataFrame的apply方法可以实现这个功能:
f=lambda x:x.max()-x.min()
frame.apply(f)
#b 2.844177
#d 2.175263
#e 1.429693
#dtype: float64
这里的函数f,可以用来计算Series最大值和最小值的差,会被frame的每一列调用一次。结果是一个以frame的列作为索引的Series。
若给apply传递参数axis=’columns’,函数则是每一行调用一次。
传递给apply的函数不一定是返回一个标量值,也可以带有多个值的Series:
def f(x):
return pd.Series([x.min(),x.max()],index=['min','max'])
frame.apply(f)
逐元素的Python函数也可以使用。通过applymap方法,例如:
f=lambda x:'%.2f'% x
frame
frame.map(f)
2.7排序和排名
排序
根据某些准则对数据集进行排序是另一个重要的内建操作。如果需要按行或者列索引进行字典型排序,需要使用sort_index方法,该方法会返回一个新的、排序好的对象:
和之前的一样,通过输入axis=1来让DataFrame按照行排序,通过输入ascending=False来设定排序为降序(默认升序)。
如果想要按照Series的值进行排序,则需要使用sort_values方法,在这种情况下,所有的缺失值都会默认排到Series尾部。而用sort_values方法排序DataFrame,通常通过传入参数by=索引名。传递多个索引名的列表时,按顺序依次排序。
排名
是对数组从1到有效数组点总数分配名次的操作。Series和DataFrame是通过rank实现排名。
排名顺序可以通过不同的方法来打破。通过输入参数method=first,平级打破方法还有很多,可以自行搜索。
2.8含有重复标签的轴索引
实际情况中可能出现重复索引的情况,通过obj.is_unique
可以判断出标签是否唯一。
重复索引的情况下,一个标签索引会返回一个序列。
3描述性统计的概述与计算
pandas对象装配了一个常用数学、统计学方法的集合。其中大部分归属于归约或汇总统计的类别
这些方法从DataFrame的行或列中抽取一个Series或一系列值得单个值:
df=pd.DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]],index=list('abcd'),columns=['one','two'])
df.sum()
df.sum(axis=1)
df.mean(axis=1,skipna=False)
axis=1来计算按列求解每一行得解,skipna=False来让代码不跳过NA值,level可以用来缩减分组层级。
除了上述得归约类方法,还有积累型方法,例如cumsum。
还有一种方法两者都不是,例如describe,它能一次性产生多个汇总统计。
对于非数值型数据,descripe会产生林一种汇总统计:
描述性统计和汇总性统计
count | 计算非NA的个数 |
---|---|
describe | 计算Series或DataFrame各列的汇总统计集合 |
min、max | 计算最小值、最大值 |
idxmin、idxmax | 最小最大的索引标签 |
argmin、argmax | 最小最大的索引位置(数字) |
quantile | 计算从0到1的分位数 |
sum | 加和 |
mean | 均值 |
median | 中位数 |
mad | 平均值的平均绝对偏差 |
prod | 所有值的积 |
var | 样本方差 |
std | 标准差 |
skew | 样本偏度值 |
kurt | 样本峰度值 |
cumsum、cumprod | 累加、累积 |
cummin、cummax | 累计值最大最小 |
diff | 计算第一个算数差值 |
pct_change | 计算百分比 |
3.1相关性和协方差
一些汇总统计、比如协方差和相关性,是由多个参数计算出的。
DataFrame的corr和cov方法会分别以DataFrame的形式,返回相关性和协方差矩阵。
corrwith则可以用来计算DataFrame的行或列与另一个序列或DataFrame的相关性。
3.2唯一值、计数和成员属性
唯一值和之前的计算方法一样,还是通过unique方法,计数则是使用value_counts。isin则用来判断成员是否属于该列中,返回一个布尔值Series。