pandas是一个强大的工具,他有两种主要的数据结构:Series和DataFrame,还有一些基于这两种结构的基本功能,以及汇总和统计功能,接下来会分4篇博客来详细的介绍pandas的使用。这4篇博客的主题为:
2)Series和DataFrame的索引、切片、过滤,算术运算与数据对齐,函数映射,排序等
3)Series和DataFrame的汇总和计算统计描述
4)Series和DataFrame的层次化索引
本篇博客主要讲述Series和DataFrame的基本功能,包括索引、切片、过滤,算术运算与数据对齐,函数映射,排序等,内容安排如下所示:
1)重新索引
2)丢弃指定轴上的项
3)索引、选取和过滤
4)算术运算和数据对齐
5)函数应用和映射
6)排序
7)带有重复值的轴索引
该功能主要是为了解决什么问题呢?应该是时间序列这样的数据,有时间点缺失的填充问题。主要的实例方法是.reindex(),可以处理Series和DataFrame类型的数据重新索引。
import pandas as pd
from pandas import Series,DataFrame
objSeries1 = Series(range(6),index = ['a','d','e','f','g','h'])
objSeries1
a 0
d 1
e 2
f 3
g 4
h 5
dtype: int64
objSeries2 = objSeries1.reindex(['a','b','c','d','e','f','g','h'])
objSeries2#系统自动在缺失索引填充NaN
a 0.0
b NaN
c NaN
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries1
a 0
d 1
e 2
f 3
g 4
h 5
dtype: int64
objSeries1.reindex(['a','b','c','d','e','f','g','h'],fill_value = 10)
a 0
b 10
c 10
d 1
e 2
f 3
g 4
h 5
dtype: int64
objSeries1
a 0
d 1
e 2
f 3
g 4
h 5
dtype: int64
注意,reindex不改变原数据
reindex函数的参数如下表所示:
参数 | 说明 |
---|---|
index | 用作索引的新序列,既可以是Index实例,也可以是其他序列的python数据结构,Index会被完全使用 |
method | 插值(填充)方式,具体参数请见下表 |
fill_value | 在重新索引的过程中,需要引入缺失值时使用的替代值 |
limit | 前向和后向填充时的最大填充量 |
level | 在MultiIndex的指定级别上匹配简单索引,否则选取其子集 |
copy | 默认为True,无论如何都到赋值,如果为False,则新旧相等就不复制?(不太懂) |
对于时间序列的有序数据,重新索引时可以做一些插值处理。method方法可以达到此目的,method插值选项如下表所示:
参数 | 说明 |
---|---|
ffill或pad | 前向填充 |
bfill或backfill | 后向填充 |
objSeries3 = Series(['a','b','c'],index = [0,2,4])
objSeries3.reindex(range(6),method = 'ffill')
0 a
1 a
2 b
3 b
4 c
5 c
dtype: object
objSeries3
0 a
2 b
4 c
dtype: object
下面来看一下DataFrame的重新索引,对于DataFrame,reindex可以修改行、列索引,也可以两个都修改,如果仅传入一列,则会重新索引行。
import numpy as np
frame = DataFrame(np.arange(9).reshape(3,3),index = ['a','b','c'],columns = ['0hio','stata','texas'])
frame
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
b | 3 | 4 | 5 |
c | 6 | 7 | 8 |
frame.reindex(['a','b','c','d'],method = 'ffill')#插值只能按行进行即纵轴(1轴)
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
b | 3 | 4 | 5 |
c | 6 | 7 | 8 |
d | 6 | 7 | 8 |
reColumns = ['stata','utah','texas']
frame.reindex(columns = reColumns,method = 'ffill')#插值只能按行进行即纵轴(1轴)
stata | utah | texas | |
---|---|---|---|
a | 1 | NaN | 2 |
b | 4 | NaN | 5 |
c | 7 | NaN | 8 |
插值只能按行进行即纵轴(1轴)
还可以利用ix的标签索引功能
frame.ix[['a','b','c','d'],['stata','utah','texas']]
stata | utah | texas | |
---|---|---|---|
a | 1.0 | NaN | 2.0 |
b | 4.0 | NaN | 5.0 |
c | 7.0 | NaN | 8.0 |
d | NaN | NaN | NaN |
1)重新索引不改变原数据,会返回新的Series或者DataFrame
2)插值只能按行进行即纵轴(1轴)
采用drop方法返回一个在指定轴上删除指定值的新对象
#Series对象
objSeries2
a 0.0
b NaN
c NaN
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries2.drop(['b','c'])
a 0.0
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries2
a 0.0
b NaN
c NaN
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries2New = objSeries2.drop(['b','c'])
objSeries2New
a 0.0
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries2New['d'] = 6
objSeries2New
a 0.0
d 6.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries2New.sort_values()
a 0.0
e 2.0
f 3.0
g 4.0
h 5.0
d 6.0
dtype: float64
objSeries2New
a 0.0
d 6.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries2
a 0.0
b NaN
c NaN
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
注意删除不改变原数据,返回一个新对象,新对象不是原对象的引用
#DataFrame对象
frame
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
b | 3 | 4 | 5 |
c | 6 | 7 | 8 |
frame.drop('b')
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
c | 6 | 7 | 8 |
frame.drop(['0hio','stata'],axis=1)#删除纵轴时,需要指定axis=1
texas | |
---|---|
a | 2 |
b | 5 |
c | 8 |
注意删除DataFrame时,需要指定axis=1
主要分为三部分:1)根据索引号或者顺序整数索引,选取一个value;2)根据切片选取连续几个values;3)逻辑过滤
objSeries1
a 0
d 1
e 2
f 3
g 4
h 5
dtype: int64
1)根据索引号或者顺序整数索引
objSeries1[2]
2
objSeries1['d']
1
2)根据切片选取连续几个values
objSeries1[2:5]#不包含5
e 2
f 3
g 4
dtype: int64
objSeries1['e':'h']#包含末端5
e 2
f 3
g 4
h 5
dtype: int64
注意,Series的索引切片和numpy的整数索引有所不同,Series索引切片包含末端,而numpy整数索引切片不包含
3)逻辑过滤
objSeries1[objSeries1>3]
g 4
h 5
dtype: int64
对DatatFrame对象的进行索引就是获得一个或多个列,主要分为三部分:1)根据列索引号或者顺序整数索引切片,某一列或多列,行可以通过切片选择多行;2).ix行列索引;3)逻辑过滤
1)根据列索引号或者顺序整数索引切片,某一列或多列,行可以通过切片选择多行
frame
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
b | 3 | 4 | 5 |
c | 6 | 7 | 8 |
frame['0hio']
a 0
b 3
c 6
Name: 0hio, dtype: int32
frame[:1]
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
frame['0hio':'texas']
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
b | 3 | 4 | 5 |
c | 6 | 7 | 8 |
注意,类似frame[1]进行行列选择是错误的需用.ix
2).ix行列索引
frame.ix[1,1]
4
frame.ix[1]
0hio 3
stata 4
texas 5
Name: b, dtype: int32
frame.ix[['a','b'],['0hio','stata']]
0hio | stata | |
---|---|---|
a | 0 | 1 |
b | 3 | 4 |
frame.ix[0:2]
0hio | stata | texas | |
---|---|---|---|
a | 0 | 1 | 2 |
b | 3 | 4 | 5 |
frame.ix['a':'b','0hio':'stata']
0hio | stata | |
---|---|---|
a | 0 | 1 |
b | 3 | 4 |
3)逻辑过滤
frame < 4
0hio | stata | texas | |
---|---|---|---|
a | True | True | True |
b | True | False | False |
c | False | False | False |
frame[frame < 4]
0hio | stata | texas | |
---|---|---|---|
a | 0.0 | 1.0 | 2.0 |
b | 3.0 | NaN | NaN |
c | NaN | NaN | NaN |
frame[frame < 4] = 0
frame
0hio | stata | texas | |
---|---|---|---|
a | 0 | 0 | 0 |
b | 0 | 4 | 5 |
c | 6 | 7 | 8 |
frame.ix[frame.stata > 3,:2]
0hio | stata | |
---|---|---|
b | 0 | 4 |
c | 6 | 7 |
pandas自动的数据对齐操作在不重叠索引处引入NA值。缺失值会在算术运算中传播
objSeries1
a 0
d 1
e 2
f 3
g 4
h 5
dtype: int64
objSeries2
a 0.0
b NaN
c NaN
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries2['b':'c'] = 10
objSeries2
a 0.0
b 10.0
c 10.0
d 1.0
e 2.0
f 3.0
g 4.0
h 5.0
dtype: float64
objSeries4 = objSeries2['a':'f']
objSeries4
a 0.0
b 10.0
c 10.0
d 1.0
e 2.0
f 3.0
dtype: float64
##结果,pandas自动的数据对齐操作在不重叠索引处引入NA值。缺失值会在算术运算中传播
objSeries1 + objSeries4
a 0.0
b NaN
c NaN
d 2.0
e 4.0
f 6.0
g NaN
h NaN
dtype: float64
frame
0hio | stata | texas | |
---|---|---|---|
a | 0 | 0 | 0 |
b | 0 | 4 | 5 |
c | 6 | 7 | 8 |
frame1 = frame.ix['a':'b',:2]
frame1
0hio | stata | |
---|---|---|
a | 0 | 0 |
b | 0 | 4 |
frame1['add'] = 10
frame1
0hio | stata | add | |
---|---|---|---|
a | 0 | 0 | 10 |
b | 0 | 4 | 10 |
frame1.ix['f'] = 12
frame2 = frame.drop('f')
frame2
0hio | stata | texas | |
---|---|---|---|
a | 0 | 0 | 0 |
b | 0 | 4 | 5 |
c | 6 | 7 | 8 |
frame2 + frame1
0hio | add | stata | texas | |
---|---|---|---|---|
a | 0.0 | NaN | 0.0 | NaN |
b | 0.0 | NaN | 8.0 | NaN |
c | NaN | NaN | NaN | NaN |
f | NaN | NaN | NaN | NaN |
frame2.add(frame1,fill_value = 0)
0hio | add | stata | texas | |
---|---|---|---|---|
a | 0.0 | 10.0 | 0.0 | 0.0 |
b | 0.0 | 10.0 | 8.0 | 5.0 |
c | 6.0 | NaN | 7.0 | 8.0 |
f | 12.0 | 12.0 | 12.0 | NaN |
frame1.add(frame2,fill_value = 0)#不知道什么情况不没有完全补充0??
0hio | add | stata | texas | |
---|---|---|---|---|
a | 0.0 | 10.0 | 0.0 | 0.0 |
b | 0.0 | 10.0 | 8.0 | 5.0 |
c | 6.0 | NaN | 7.0 | 8.0 |
f | 12.0 | 12.0 | 12.0 | NaN |
常用的算术运算
方法 | 说明 |
---|---|
add | 加法 |
sub | 减法 |
div | 除法 |
mul | 乘法 |
frame
0hio | stata | texas | |
---|---|---|---|
a | 0 | 0 | 0 |
b | 0 | 4 | 5 |
c | 6 | 7 | 8 |
f | 12 | 12 | 12 |
objSeries4
a 0.0
b 10.0
c 10.0
d 1.0
e 2.0
f 3.0
dtype: float64
frame - objSeries4
0hio | a | b | c | d | e | f | stata | texas | |
---|---|---|---|---|---|---|---|---|---|
a | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
b | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
c | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
f | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
frame.sub(objSeries4,axis = 0)#利用算术运算,可以改变轴向
0hio | stata | texas | |
---|---|---|---|
a | 0.0 | 0.0 | 0.0 |
b | -10.0 | -6.0 | -5.0 |
c | -4.0 | -3.0 | -2.0 |
d | NaN | NaN | NaN |
e | NaN | NaN | NaN |
f | 9.0 | 9.0 | 9.0 |
numpy的ufunc函数(元素级数组方法)也可以用于操作pandas对象,
此外,还有apply()作用于DataFrame的一列(纵轴)或一行(横轴)、applymap()函数作用于DataFrame元素级
frame
0hio | stata | texas | |
---|---|---|---|
a | 0 | 0 | 0 |
b | 0 | 4 | 5 |
c | 6 | 7 | 8 |
f | 12 | 12 | 12 |
frame[frame < 4] =4
frame
0hio | stata | texas | |
---|---|---|---|
a | 4 | 4 | 4 |
b | 4 | 4 | 5 |
c | 6 | 7 | 8 |
f | 12 | 12 | 12 |
np.sqrt(frame)
0hio | stata | texas | |
---|---|---|---|
a | 2.000000 | 2.000000 | 2.000000 |
b | 2.000000 | 2.000000 | 2.236068 |
c | 2.449490 | 2.645751 | 2.828427 |
f | 3.464102 | 3.464102 | 3.464102 |
frame.apply(lambda x:x.max() - x.min())
0hio 8
stata 8
texas 8
dtype: int64
func = lambda x:x.max() - x.min()
frame.apply(func,axis = 0)#纵轴
0hio 8
stata 8
texas 8
dtype: int64
frame.apply(func,axis = 1)#横轴
a 0
b 1
c 2
f 0
dtype: int64
frame
0hio | stata | texas | |
---|---|---|---|
a | 4 | 4 | 4 |
b | 4 | 4 | 5 |
c | 6 | 7 | 8 |
f | 12 | 12 | 12 |
format = lambda x:'%0.2f'%x
frame.applymap(format)
0hio | stata | texas | |
---|---|---|---|
a | 4.00 | 4.00 | 4.00 |
b | 4.00 | 4.00 | 5.00 |
c | 6.00 | 7.00 | 8.00 |
f | 12.00 | 12.00 | 12.00 |
#Series也有map方法
frame.stata.map(format)
a 4.00
b 4.00
c 7.00
f 12.00
Name: stata, dtype: object
排序的方法有很多,主要有以下几种:
1)python内置的sorted()
2)numpy里的.sort()或np.sort()
3)pandas里的.sort_index(),.sort_values()
4)Series中的.order()
注意不同工具包返回的结果类型不一样
objSeries4
a 0.0
b 10.0
c 10.0
d 1.0
e 2.0
f 3.0
dtype: float64
objSeries4.sort_index()
a 0.0
b 10.0
c 10.0
d 1.0
e 2.0
f 3.0
dtype: float64
objSeries4.sort_values()
a 0.0
d 1.0
e 2.0
f 3.0
b 10.0
c 10.0
dtype: float64
frame3 = frame.reindex(['a','c','f','b']).reindex(columns = ['texas','0hio','stata'])#多了一个轴向的选择
frame3
texas | 0hio | stata | |
---|---|---|---|
a | 4 | 4 | 4 |
c | 8 | 6 | 7 |
f | 12 | 12 | 12 |
b | 5 | 4 | 4 |
frame3.sort_index(axis=0)#纵轴(行索引)排序
texas | 0hio | stata | |
---|---|---|---|
a | 4 | 4 | 4 |
b | 5 | 4 | 4 |
c | 8 | 6 | 7 |
f | 12 | 12 | 12 |
frame3.sort_index(axis = 1)#横轴(列索引)排序
0hio | stata | texas | |
---|---|---|---|
a | 4 | 4 | 4 |
c | 6 | 7 | 8 |
f | 12 | 12 | 12 |
b | 4 | 4 | 5 |
frame3
texas | 0hio | stata | |
---|---|---|---|
a | 4 | 4 | 4 |
c | 8 | 6 | 7 |
f | 12 | 12 | 12 |
b | 5 | 4 | 4 |
frame3.sort_values(by='stata')#默认纵轴
texas | 0hio | stata | |
---|---|---|---|
a | 4 | 4 | 4 |
b | 5 | 4 | 4 |
c | 8 | 6 | 7 |
f | 12 | 12 | 12 |
frame3
texas | 0hio | stata | |
---|---|---|---|
a | 4 | 4 | 4 |
c | 8 | 6 | 7 |
f | 12 | 12 | 12 |
b | 5 | 4 | 4 |
注意,.sort_index、.sort_values不改变原数据,此外,注意DaraFrame的平级关系,即对某一列排序,其他列也会跟着变化
frame3.ix['c'].order()#实现横轴方向排序。
C:\Program Files\anaconda\lib\site-packages\ipykernel\__main__.py:1: FutureWarning: order is deprecated, use sort_values(...)
if __name__ == '__main__':
0hio 6
stata 7
texas 8
Name: c, dtype: int64
pandas允许出现重复的轴索引,那么怎么处理重复轴索引问题呢?.is_unique()可以检测出索引是否是唯一的,而利用重复轴索引时,会返回多行多列
obj = Series(range(5),index = ['a','a','b','b','c'])
obj
a 0
a 1
b 2
b 3
c 4
dtype: int64
obj.index.is_unique
False
obj['a']
a 0
a 1
dtype: int64
df = DataFrame(np.random.randn(4,3),index = ['a','a','b','b'])
df
0 | 1 | 2 | |
---|---|---|---|
a | -0.224366 | 0.250954 | -0.733037 |
a | 0.973195 | -0.246500 | 0.895259 |
b | 1.889028 | 0.229811 | 2.205712 |
b | 1.407430 | 1.379889 | 0.533036 |
df.index.is_unique
False
df.ix['a']
0 | 1 | 2 | |
---|---|---|---|
a | -0.224366 | 0.250954 | -0.733037 |
a | 0.973195 | -0.246500 | 0.895259 |
pandas的数据处理总是不改变原数据,而是返回新的结果。