利用python进行数据分析

Numpy基础(数组和矢量计算)

numpy功能

1
2
3
4
5
6
7
8
9
10
1.高性能科学计算和数据分析的基础包
2.部分功能:
2.1 ndarray:具有矢量算术运算+复杂广播能力的多维数组
2.2 快速运算的标准数学函数
2.3 读写磁盘数据的工具
2.4 操作内存映射文件的工具
2.5 线性代数
2.6 随机数生成
2.7 傅里叶变换功能
2.8 集成代码的工具

多维数组对象(ndarray)

1
2
3
4
1.ndarray是一个通用的同构数据多维容器(所有元素必须是同类型的)
2.每个数组:
一个shape表示各维度大小的元组 (2,3) 就是两行三列
一个dtype用于说明数组数据类型的对象 float64 就是float类型64位

创建ndarray

函数总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import numpy as np
#普通序列
data1=[6,7.5,8,0,1]
arr1=np.array(data1)
print(arr1)
#嵌套序列
data2=[[1,2,3,4],[5,6,7,8]]
arr2=np.array(data2)
print(arr2)
print(f"arr1的维度:{arr1.shape}")
print(f"arr2的维度:{arr2.shape}")
print(f"arr1的数据类型:{arr1.dtype}")
print(f"arr2的数据类型:{arr2.dtype}")

#函数新建数组
##创0
data3=np.zeros(10) #创建10个
data33=np.zeros((3,6)) #创建3行6列
data333=np.empty(10) #多数情况下返回的是未初始化的垃圾值

##创1
data4=np.ones(10) #创建10个

print(data3)
print(data33)
print(data333)
print(data4)

#函数常见n*n的单位矩阵(主对角线为1,其余为0)
data5=np.eye(5)
print(data5)

执行结果

ndarray数据类型

数据类型总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
#创建arr
arr1=np.array([1,2,3],dtype=np.float64) #创建时候给出内容和dtype
arr2=np.array([1,2,3],dtype=np.int32)
print(arr1.dtype)
print(arr2.dtype)

#astype方法显式转换dtype ---> 创建出一个新的数组(原始数据的一份拷贝)
arr1=np.array([1,2,3,4,5])
#int32
print(arr1.dtype)
float_arr=arr1.astype(np.float64)
#float64
print(float_arr.dtype)

执行结果

数组和标量之间的运算

1
2
3
4
5
6
7
8
9
import numpy as np
#创建arr
arr=np.array([[1.,2.,3],[4.,5.,6.]]) 两行列表
print(arr)
print(arr*arr)
print(arr-arr)
#数组与标量的算术运算
print(1/arr)
print(arr**0.5)

执行结果

基本的索引和切片

一维数组

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
#创建arr
arr=np.arange(10)
#输出arr所有元素
print(arr)
#输出第6位元素
print(arr[5])
#输出6-8位元素
print(arr[5:8])
#将6-8位元素值都更改为100
arr[5:8]=100
#重新输出
print(arr)

执行结果

1
2
3
4
5
6
7
8
9
10
import numpy as np
#创建arr
arr=np.arange(10)
print(arr)
arr_slice=arr[5:8] #形成切片
arr_slice[1]=12345 #只改切片的第一个
print(arr)
#切片所有都改
arr_slice[:]=1000
print(arr) #arr也会被改变

执行结果

高维数组

索引列表

1
2
3
4
5
6
7
8
9
10
import numpy as np
#创建arr
arr=np.array([[1,2,3],[4,5,6],[7,8,9]])
#输出原始数组
print(arr)
#第二个 一位数组
print(arr[2])
#索引列表(逗号隔开) --> 单个元素
print(arr[0][2])
print(arr[0,2])

执行结果

切片索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
#创建arr
arr=np.array([[1,2,3],[4,5,6],[7,8,9]])
#输出原始数组
print(arr)

#1.一维对象
arr1=arr[1:3] #输出从1轴到2轴
print(arr1)

#2.多维对象
##2.1一个/多个轴进行切片
arr2=arr[:2] #输出0轴开始到1轴
print(arr2)

arr3=arr[:2,1:] #h横:输出0轴到1轴 竖:输出1轴到最后轴
print(arr3)

执行结果

1
2
3
4
5
6
7
8
import numpy as np
#创建arr
arr=np.array([[1,2,3],[4,5,6],[7,8,9]])
##2.2整数索引混合进行切片
arr4=arr[1,:2] #横:输出1轴 竖:输出0轴到1轴
print(arr4)
arr5=arr[2,:1] #横:输出2轴 竖:输出0轴
print(arr5)

执行结果

布尔型索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
#创建 数组(存储数据)+数组(存储姓名)
names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
data=np.random.randn(7,4)
print(names)
print(data)
print(names=='Bob') #数组的比较是矢量化的 ---> 产生一个布尔型数组
#数组索引
print(data[names=='Bob']) #Bob对应的那些数字行
#混合使用
print(data[names=='Bob',2:]) #Bob对应的那些的2轴到最后一轴
#进行否定: 不等于!= 负号-
print(data[names!='Bob'])
print(data[~(names=='Bob')])
#z组合布尔条件 和& 或|
res=(names=='Bob')|(names=='Will') #or和and关键字在布尔型数组会无效
print(data[res])

执行结果

花式索引

1
2
3
4
5
6
7
8
9
10
11
import numpy as np
arr=np.empty((8,4)) #创建一个8行4列的数组
for i in range(8): #每行赋当前行的值
arr[i]=i
print(arr) #输出数组所有元素

#特定顺序选取行子集 ---> 传入一个整数列表/ndarray(指定顺序)
##1.正数 从开头开始
print(arr[[4,3,0,6]]) 输出4 3 0 6 四行
##2.负数 从末尾开始
print(arr[[-3,-5,-7]]) 输出5 3 1 三行

执行结果

数组转置和轴对称

reshape函数

1
2
3
4
5
6
7
import numpy as np
arr=np.arange(32).reshape((8,4))
print(arr)
#选取下标(1,0),(5,3),(7,1),(2,2)
print(arr[[1,5,7,2],[0,3,1,2]])
#使用n.p.ix_函数 将两个一维整数数组->用于选取方形区域的索引器
print(arr[np.ix_([1,5,7,2],[0,3,1,2])])

执行结果

转置和轴对称函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
arr=np.arange(15).reshape((3,5))
print(arr)
#转置(跟线代置换一样 横对竖)
print(arr.T) #轴兑换.T

#矩阵内积XT X np.dot
arr2=np.random.randn(6,3) # 构建6行3列
print(arr2,arr2.T) # 6行3列 3列6行 --> 6行6列
print(arr2.T,arr2)

#转置(高维数组) 元组(轴编号组成)才能对这些轴进行转置
arr3=np.arange(16).reshape((2,2,4)) #三维x=2,y=2,z=4
print(arr3)
print(arr3.transpose((1,0,2)))

#swapaxes方法[需要接受一对轴编号]
print(arr3.swapaxes(1,2))

执行结果

通用函数(元素级数组函数)

1
2
3
4
1.通用函数(ufunc):一种对ndarray中的数据执行元素级运算的函数
2.通用函数:矢量化包装器
输入:一个/多个标量值
输出:一个/多个标量值

一元通用函数

二元通用函数

数组进行数据处理

1
2
3
4
5
6
7
8
9
10
11
#假设我们想要在一组值(网格型)上计算函数sqrt(x^2+y^2)
#np.meshgrid函数
两个一维数组 --> 两个二维矩阵(所有的(X,Y)对)

import numpy as np
points=np.arange(-5,5,0.01) #1000个间隔相等的点
#生成(X,Y)对
xs,ys=np.meshgrid(points,points)
#获取sqrt(X^2+Y^2)
z=np.sqrt(xs**2+ys**2)
print(z)

条件逻辑(数组运算)

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
xarr=np.array([1.1,1.2,1.3,1.4,1.5])
yarr=np.array([2.1,2.2,2.3,2.4,2.5])
cond=np.array([True,False,True,True,False])

#根据判断cond的值为True选取xarr的值Flase选取yarr的值
result=np.where(cond,xarr,yarr) #第二个和第三个参数可以是数组
print(result)

#根据判断xarr大于1.3赋值2小于1.3赋值1
result2=np.where(xarr>1.3,2,1) #第二个和第三个参数可以是标量值
print(result2)

数学和统计方法

基本数组统计方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
#正态分布的数据
arr=np.random.randn(5,4)
print(arr)
print(arr.sum()) #数组中全部/某轴向的元素求和
print(arr.mean()) #算数平均数
print(arr.min()) #最小值
print(arr.max()) #最大值
print(arr.argmin()) #最小元素索引
print(arr.argmax()) #最大元素索引
print(arr.cumsum()) #所有元素累计和
print(arr.cumprod()) #所有元素累计积
print(arr.std()) #标准差
print(arr.var()) #方差

布尔型数组的方法

1
2
3
4
5
6
7
8
9
10
import numpy as np
#布尔值会被强制转换为1(True)和0(False)
arr=np.random.randn(100)
print(arr)
print((arr>100).sum())

#any和all
arr2=np.array([False,False,True,False])
print(arr2.any()) #测试是否存在一个/多个True 测试是否存在一个/多个非0元素
print(arr2.all()) #测试是否所有值都是True 测试是否所有值都是非0元素

排序(sort方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np

#一维数组
arr=np.random.randn(8)
print(arr)
#排序sort方法
arr.sort()
print("排序之后的:")
print(arr)

#多维数组
arr=np.random.randn(5,3)
print(arr)
arr.sort(1) #对轴进行排序 就是每行自己排序
print("排序之后的:")
print(arr)

数组的集合运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np

names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
#unique()只返回不重复的名字有几个
print(np.unique(names))

arr1=np.array([1,2,3,4,5,5,5,6,6,6,8,8,8,9,9,91,123,456,123])
arr2=np.array([1,2,3,5,4,9,6,9,123,45678,789])
#unique()只返回不重复的名字有几个
print(np.unique(arr1))
#intersect1d(x,y)返回x和y的公共元素
print(np.intersect1d(arr1,arr2))
#union1d(x,y)返回x和y的并集
print(np.union1d(arr1,arr2))
#int1d(x,y)返回布尔型数组(x的元素是否包含在y之内) 大小是x数组的长度
print(np.in1d(arr1,arr2))
#setdiff1d(x,y)返回集合的差(就是在x之中,不在y中)
print(np.setdiff1d(arr1,arr2))
print(np.setdiff1d(arr2,arr1))
#setxor1d(x,y)返回集合的对称差(只在一个数组但是不同时在两个数组 --有可能在x不在y 有可能在y不在x)
print(np.setxor1d(arr1,arr2))

数组的文件输入输出(文本/二进制数据)

保存到磁盘(save和load)

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
#默认情况下,数组保存在.npy的文件(未压缩的原始二进制格式)
arr=np.arange(10) #按照顺序输出10个数字0-9
print(arr)

#save() 将arr数组存到名为some_array的文件
np.save('some_array',arr) #存一个数组
np.savez('array_archive.npz',a=arr,b=arr) #存多个数组(数组以关键字参数的形式传入)

#load去加载磁盘的文件(自动添加扩展名)
np.load('some_array.npy')
res=np.load('array_archive.npz') #得到类似字典的对象 对各个数组进行延迟加载
print(res['b'])

存取文本文件

1
2
3
#1.python中的文件读写函数
#2.pandas中的read_csv和read_table函数
#3.numpy中的loadtxt和genfromtxt函数

线性代数(linalg)

常用的numpy.linalg函数

1
2
3
4
5
6
7
8
import numpy as np
from numpy.linalg import inv,qr
x=np.array([[1.,2.,3.],[4.,5.,6.]])
y=np.array([[6.,23.],[-1,7],[8,9]])
print(x)
print(y)
#np.dot(x,y) <-> x.dot(y)
print(x.dot(y))

随机数生成(random)

random函数

1
2
3
4

import numpy as np
samples=np.random.normal(size=(4,4))
print(samples)

pandas入门

1
2
3
4
5
6
7
8

1.pandas基于NumPy构建
2.写代码导包
from pandas import Series,DataFrame
import pandas as pd
3.主要数据类型:
Series 类似于一维数组的对象 (数据+数据标签)
DataFrame

Series(像字典)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np
from pandas import Series,DataFrame
import pandas as pd

#不指定索引
obj=Series([4,7,-5,3])
#索引(0-N-1) 值
print(obj)
#所有值
print(obj.values)
#所有索引
print(obj.index)

#指定索引
obj2=Series([4,7,-5,3],index=['d','b','a','c'])
print(obj2)
print(obj2.index)

#保留numpy数组运算(保留索引和值之间的链接)
print(obj2[obj2>0])
print(obj2*2)
print(np.exp(obj2))

DataFrame(表格型)

DataFrame创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import numpy as np
from pandas import Series,DataFrame
import pandas as pd

#1.直接传入一个字典(等长列表/numpy数组)
data={
'state':['Ohio','Ohio','Ohio','Nevada','Nevada'],
'year':[2000,2001,2002,2001,2002],
'pop':[1.5,1.7,3.6,2.4,2.9]
}
frame=DataFrame(data)
print(frame)

#指定列序列(dataframe根据指定顺序进行排列)
frame1=DataFrame(data,columns=['year','state','pop']) #data字典要根据列来排序
print(frame1)

#指定列序列(传入的列在数据中找不到,产生NA值)
frame2=DataFrame(data,columns=['year','state','pop','debt']) #debt没有就所有都显示NA
frame3=DataFrame(data,columns=['year','state','pop','debt'],index=['one','two','three','four','five']) #debt没有就所有都显示NA index变成英文
print(frame2)
print(frame3)


#2.嵌套字典(字典中的字典) ---> 外层字典的键作为列 内层字典的键作为行索引
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
#2.嵌套字典(字典中的字典) ---> 外层字典的键作为列 内层字典的键作为行索引
pop={'Nevada':{2001:2.4,2002:2.9},
'Ohio':{2000:1.5,2001:1.7,2002:3.6}} # 列:Nevada,Ohio 行:2000,2001,2002
frame3=DataFrame(pop)
print(frame3)

第一种方式

第二种方式

DataFrame使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
#1.直接传入一个字典(等长列表/numpy数组)
data={
'state':['Ohio','Ohio','Ohio','Nevada','Nevada'],
'year':[2000,2001,2002,2001,2002],
'pop':[1.5,1.7,3.6,2.4,2.9]
}
#指定列序列(传入的列在数据中找不到,产生NA值)
frame2=DataFrame(data,columns=['year','state','pop','debt']) #debt没有就所有都显示NA
print(frame2)
frame2['debt']=16.5 #修改长度和DataFrame长度相匹配!!!!!!!!!
print(frame2)

索引对象

Index对象

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
#轴标签和其他元数据(比如轴名称)
#a 0
#b 1
#c 2
obj=Series(range(3),index=['a','b','c']) # Series/DataFrame构造用到的任何数组/其他序列的标签 --> Index
index=obj.index
print(index) # a b c
print(index[1:]) # b c

index[1]='d' #index对象不可以修改

Index的方法和属性

基本功能

重新索引(reindex)

reindex函数的参数

method选项(前向/后向填充)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# d 4.5
# b 7.2
# a -5.3
# c 3.6
obj=Series([4.5,7.2,-5.3,3.6],index=['d','b','a','c'])
print(obj)
# a -5.3
# b 7.2
# c 3.6
# d 4.5
# e NAN
obj2=obj.reindex(['a','b','c','d','e']) #缺失的赋值为NAN
print(obj2)
# a -5.3
# b 7.2
# c 3.6
# d 4.5
# e 0
obj3=obj.reindex(['a','b','c','d','e'],fill_value=0) #缺失的赋值为0
print(obj3)

丢弃指定轴上的项(drop)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
#一个索引数组/列表 --> 丢弃某条轴上的一个/多个项
#a 0.0
#b 1.0
#c 2.0 (丢弃)
#d 3.0
#e 4.0
obj=Series(np.arange(5.),index=['a','b','c','d','e'])
print(obj)
#丢弃c
new_obj=obj.drop('c')
print(new_obj)

索引+选取+过滤

Series索引(啥都有)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# a 0.0
# b 1.0
# c 2.0
# d 3.0
obj=Series(np.arange(4.),index=['a','b','c','d'])
print(obj)

#输出b的索引为1.0
print(obj['b'])

#输出1行的索引值为1.0
print(obj[1])

#输出第三行和第四行
print(obj[2:4])
#利用标签的切片是闭环!!!!!
print(obj['b':'c']) #py切片运算是不包含的最后一个

#输出三行
print(obj[['b','a','d']])

#输出第二行和第三行
print(obj[[1,3]])

#输出前两行
print(obj[obj<2])

DataFrame索引(一个/多个列)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
data=DataFrame(np.arange(16).reshape((4,4)), #随机数分为4*4
index=['Ohio','Colorado','Utah','New York'], #列
columns=['one','two','three','four'] #行
)
print(data)
print()
#1
#5
#9
#13
print(data['two'])
print()
#2 0
#6 4
#10 8
#14 12
print(data[['three','one']])
print()

#选取

#1.第一种
##选取第一行和第二行
print(data[:2])
print()

##选取第三列中大于5的行
print(data['three']>5)
print()

#2.第二种(更像是ndarray数组)
##判断是否data<5
print(data<5)
print()

##将data中小于5的都改为0
data[data<5]=0
print(data)

算术运算和数据对齐

算数方法

Series(不同就赋值NaN)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# a 7.3 a -2.1
# c -2.5 c 3.6
# d 3.4 e -1.5
# e 1.5 f 4
# g 3.1
s1=Series([7.3,-2.5,3.4,1.5],index=['a','c','d','e'])
s2=Series([-2.1,3.6,-1.5,4,3.1],index=['a','c','e','f','g'])
# a 7.3-2.1=5.2
# c 3.6-2.5=1.1
# d NaN (不重叠的赋值NaN)
# e 1.5-1.5=0
# g NaN (不重叠的赋值NaN)
# f NaN (不重叠的赋值NaN)
print(s1+s2)

DataFrame(不同就赋值NaN)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# b c d
#Ohio 0.0 1.0 2.0
#Texas 3.0 4.0 5.0
#Colorado 6.0 7.0 8.0
# b d e
#Utah 0.0 1.0 2.0
#Ohio 3.0 4.0 5.0
#Texas 6.0 7.0 8.0
#Oregon 9.0 10.0 11.0
df1=DataFrame(np.arange(9.).reshape((3,3)),
columns=list('bcd'),
index=['Ohio','Texas','Colorado'],
)
df2=DataFrame(np.arange(12.).reshape((4,3)),
columns=list('bde'),
index=['Utah','Ohio','Texas','Oregon'],
)
#得到新的DataFrame[索引和列为原来的两个DataFrame的并集]
#不重叠的位置就会产生NaN值
print(df1+df2)

#填充数字 --> 使用add(DataFrame对象,full_value=值)
print(df1.add(df2,fill_value=0))

函数应用和映射(apply和ufuns方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
frame=DataFrame(np.random.randn(4,3),
columns=list('bde'),
index=['Utah','Ohio','Texas','Oregon']
)
print(frame)

#1.numpy元素级数组方法(ufuncs)
print(np.abs(frame))
#2.函数应用到一维数组(由各列/各行形成) -- apply方法
f=lambda x:x.max() - x.min()
print(frame.apply(f))
print(frame.apply(f,axis=1))

排序和排名(sort_index和sorting)

Series(根据index排序)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# d 0
# a 1
# b 2
# c 3
obj=Series(range(4),index=['d','a','b','c'])
print(obj)
# a 1
# b 2
# c 3
# d 0
print(obj.sort_index()) #缺失值默认放在Series末尾

DataFrame(根据任意轴index排序)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# d a b c
# three 0 1 2 3
# one 4 5 6 7
frame=DataFrame(np.arange(8).reshape((2,4)), #两行四列 2*4
index=['three','one'],
columns=['d','a','b','c']
)
#1.普通排序
print(frame.sort_index())
#2.更改排序
print(frame.sort_index(axis=1)) #升序(默认)
print(frame.sort_index(axis=1,ascending=False)) #降序(更改ascending属性)
#3.根据一个/多个列值排序 by属性
print(frame.sort_index(by='b'))
print(frame.sort_index(by=['b','a']))

排名(rank)

分析rank()怎么执行

https://blog.csdn.net/justinlonger/article/details/90646111

Series

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
obj=Series([7,-5,7,4,2,0,4])
#
#0 7
#1 -5
#2 7
#3 4
#4 2
#5 0
#6 4
print(obj)
# 有N个相同的元素,求和(相同元素排名)/N
print(obj.rank()) #索引0对应的元素最终排名为(6+7)/2=6.5 以此类推
print(obj.rank(ascending=False,method='max')) #所有小数进位为右边的最小整数(4.5-->5)

DataFrame

1
2
3
4
5
6
7
8
9
10
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
frame=DataFrame({
'b':[4.3,7,-3,2], # b a c 都是列名
'a':[0,1,0,1], # [x]都是值
'c':[-2,5,8,-2.5]
})
print(frame)
print(frame.rank())

带有重复值的轴索引

Series

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# a 0
# a 1
# b 2
# b 3
# c 4
obj=Series(range(5),index=['a','a','b','b','c'])
print(obj)
#测试索引是否唯一
print(obj.index.is_unique) #输出False
#索引对应多个值 --> Series
print(obj['a'])
#索引对应单个值 --> 标量值
print(obj['c'])

汇总和统计

描述和汇总统计:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# one two
# a 1.4 np.man
# b 7.1 -4.5
# c np.man np.man
# d 0.75 -1.3
df=DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]],index=['a','b','c','d'],columns=['one','two'])
#第一列 1.4+7.1+0.75=9.25
#第二列 -4.5-1.3=-5.80

#直接统计
print(df.sum())

#间接统计(达到最小值/最大值的索引)
print(df.idxmax())
print(df.idxmin())

相关系数(corr)和协方差(cov)

1
2
3
4
5
6
7
8
9
10
1.Series:
corr:计算两个Series中重叠的、非NA的、按索引对齐的值
cov:
2.DataFrame:
corr:返回DataFrame
cov:返回DataFrame

3.Series和DataFrame之间:
corrwith:3.1传入一个Series,返回一个相关系数值Series
3.2传入一个DataFrame计算按列名配对的相关系数

唯一值(unique)和值计数(value_counts)和成员资格(isin)

1
2
3
1. obj.value_counts()
2. obj.unique()
3. obj.isin(['x','y'])

处理缺失数据

NA处理方法

1
2
3
4
5
6
7
1.滤除: dropna() 默认丢弃任何含有Na的行
1.1 Series: data.dropna() / 布尔型索引 data[data.notnull()]
1.2 DataFrame:
dropna(how='all') 可以只丢弃全为na的那些行
dropna(axis=1) 只丢弃全为na的那些列

2.填充: fillna() 默认返回新对象

层次化索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
data=Series(np.random.randn(10),
index=[['a','a','a','b','b','b','c','c','d','d'],
[1,2,3,1,2,3,1,2,2,3]]
)
print(data)
#选取数据索引
print(data.index)
#选取数据子集
print(data['b'])
print(data['b':'c'])
print(data[:,2])

重排分级顺序(sortlevel)

1
2
1.swaplevel 根据两个级别的编号/名称
2.sortlevel 根据单个级别的值对数据进行排序

根据级别汇总统计(groupby)

1
1.在统计和汇总(sum) --> sum(level='xxx')

使用DataFrame的列(set_index)

1
2
1.一个/多个列 --> 行索引
2. frame.set_index(['x','y'])

数据(加载/存储/文件格式)

1
2
3
4
1.输入输出:
1.1 读取文本文件和更高效的磁盘存储格式
1.2 加载数据库中的文件
1.3 利用Web API操作网络资源

读取数据(文本格式)

读取函数介绍

pandas解析函数

1
2
1. 表格型数据 --> DataFrame对象
2. 不同的函数不同的方式

read_csv/read_table函数的参数

逐块读取文本文件(属性nrows和属性chunksize)

1
2
3
1.pd.read_csv('xx.csv',nrows=xx)
2.pd.read_csv('xx.csv',chunksize=xxx)
3.TextParser.get_chunk() 读取任意大小的块

数据写出到文本格式(to_csv)

1
2
3
4
5
6
7
8
1.data.to_csv('xx.csv')   # (默认) ,分隔符 
2.data.to_csv('xx.csv',sep='|') #sep可以更改为 |
3.data.to_csv('xx.csv',na_rep='NULL') #缺失值在输出结果中会被表示为空字符串
4.data.to_csv('xx.csv',index=False,cols=['a','b','c']) #禁掉行和列的标签

#Series
5.Series.to_csv()
6.Series.from_csv()

手工处理分隔符格式(csv.Dialect子类)

Dialect属性:

1
2
3
4
5
6
7
8
9

#1.CSV子类定义:
class dialect(csv.Dialect):
lineterminator='\n' 行结束符
delimiter=';' 分隔字段的单字符字符串
quotechar='"' 带有特殊字符的字段的引用符号

#2.csv.reader也可以接受CSV子类的各种参数
reader=csv.reader(f,delimiter='|')

JSON数据(loads和dumps方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

1.JSON简介:JavaScript Object Notation,已经成为通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。
2.JSON基本类型:对象(字典)、数组(列表)、字符串、数值、布尔值、null
3. json.loads(): JSON字符串 --> Python形式
4. json.dumps(): Python形式 --> JSON字符串

import json

obj="""
{"name":"Wes",
"places_lived":["United States","Spain","Germany"],
"pet":null,
"siblings":[{"name":"Scott","age":25,"pet":"ZuKo"},
{"name":"Katie","age":33,"pet":"Cisco"}]
}
"""
#转为Py格式
result=json.loads(obj)
print(result)

#转回json格式
asjson=json.dumps(result)

#一个/一组 json对象 --> DataFrame/数据结构(便于分析)
siblings=DataFrame(result['siblings'],columns=['name','age']) #可以选一部分的siblings 也可以选全部内容

XML和HTML(get和text_content方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
	1.python有许多可以读写html和xml格式数据的库(比如:lxml)
2. lxml.html处理html --> lxml.objectify处理xml

import json
from lxml.html import parser
from urllib2 import urlopen

#使用国内镜像下载lxml
#pip install pip install -i https://pypi.doubanio.com/simple/ --trusted-host pypi.doubanio.com --target=e:\anaconda\lib\site-packages pythonds
#在设置里面要更新编译器!!! 参考博客:https://blog.csdn.net/qq_40402685/article/details/102929846
parsed=parse(urlopen('http://finance.yahoo.com/q/op?s=AAPL+Options'))
doc=parsed.getroot()
#通过这个对象可以获取特定类型的所有html标签

#获取HTML元素的对象
#获取html中链接是<a=''> a标签 --> 使用文档根节点的findall()方法 + XPath
links=doc.findall('//a')
print(links[15:20])

#获取URL和链接文本 --> get方法(URL)和text_content方法(文本)
Ink=links[28]
Ink.get('href') # 获取地址http://finance.yahoo.com
Ink.text_content() # 获取内容 Special Editions

解析XML(lxml.objectify)

1
2
3
4
5
6
7
8
9
10

1.lxml.objectify 解析xml文件
2..getroot 得到xml文件的根节点的引用
3.root.INDICATOR 返回一个用于产生各个<INDICATOR>XML元素的生成器

import json
from lxml import objectify
path='Performance_MNR.xml'
parsed=objectify.parse(open(path))
root=parsed.getroot()

二进制数据格式(save和load方法)

1
2
3
4
5
6
7
8
9
10
11
12

import numpy as np
import pandas as pd

#pickle只能用于短期存储格式(很难保证pickle格式永远是稳定的)

#1. pandas对象的.save方法(将数据以pickle形式保存在磁盘)
frame=pd.read_csv('aaa/ex1.csv')
frame.save('aaa/frame_pickle') #保存为frame_pickle

#2. pandas.load()将数据读回Python
pd.load('aaa/frame_pickle') #读取frame_pickle

HDF5格式(层次型数据格式HDFStore类)

1
2
3
4
5
6
7

1.高效读写磁盘上二进制格式存储的科学数据
2.HDF5是一个C库(带有很多语言的 接口--JAVA/Python/Matlab)
3.一个HDF5文件 --> 一个文件系统式节点结构(存储多个数据集)
4.HDF5库的两个接口:
4.1 PyTables 抽象了HDF5的许多细节-->提供数据容器、表索引、查询功能、核外计算技术
4.2 h5py 提供一种直接而高级的HDF5 API访问接口
1
2
3
4
5
6
7
8
#h5适合"一次写 多次读"的数据集
import pandas as pd
#pandas有一个HDFStore类(类似于最小化的字典的HDFStore类)
#通过PyTables存储pandas对象
store=pd.HDFStore('mydata.h5')
store['obj1']=frame
store['obj1_col']=frame['a'] #像字典一样获取h5对象
print(store)

读取Microsoft Excel文件(ExcelFile类的xlrd和openpyxl包)

1
2
3
4
5
6
#1.传入xls或xlsx文件
xls_file=pd.ExcelFile('data.xls')
print(xls_file)

#2.通过parse读取到DataFrame
table=xls_file.parse('Sheet1')

HTML和Web API(requests包)

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
import requests
import json
#通过Python访问公共API(http://docs.python-requests.org)
url='https://www.liaoxuefeng.com/wiki/1016959663602400/1016966022717728' #随便访问一个网站
#发送一个HTTP GET请求
resp=requests.get(url)
print(resp)

#Response对象(text=‘GET请求的内容’) --> 所以loads加载一下
#许多Web API返回的都是JSON字符串(必须加载到一个Python对象)
data=json.loads(resp.text)
print(data.keys())

数据库()

关系型数据库(pandas.io.sql模块的read_frame函数)

两种方式:

1
2
3
 目前而言有两种方法:
1.通过获得元组列表然后输出
2.sql.read_frame()函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import pandas as pd
from pandas import Series,DataFrame
import json
import pandas.io.sql as sql
#嵌入式的SQLite数据库(Python内置的sqlite3驱动器)
import sqlite3

#定义test表
query="""
create table test
(
a varchar(20),
b varchar(20),
c real,
d integer
);"""

#先连接
con=sqlite3.connect(':memory:')
con.execute(query)
con.commit()

#插入几行数据
data=[('Atlanta','Georgia',1.25,6),
('Tallahassee','Florida',2.6,3),
('Sacramento','California',1.7,5)]
stmt="insert into test values(?,?,?,?)"
con.executemany(stmt,data)
con.commit()

#1.第一种 通过获得元组列表然后输出
#返回一个元组列表(大部分python sql驱动[PyODBC psycopg2 MySQLdb pymssql])
res=con.execute('select * from test')
rows=res.fetchall()
print(rows) #输出所有的结果行

#元组列表res --> DataFrame构造器(还需要列名description属性)
print(res.description)
print(DataFrame(rows,columns=zip(*res.description)[0]))


#2.read_frame函数(直接出)
res1=sql.read_frame('select * from test',con)
print(res1)

非关系型数据库(MongoDB为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
from pandas import Series,DataFrame
import json
import requests
import pymongo #MongoDB的官方驱动器

#通过默认端口27017连接MongoDB
con=pymongo.Connection('localhost',port=27017)
#访问tweets集合
tweets=con.db.tweets
#通过tweets.save将tweets逐个存入集合
url='http://search.twitter.com/search.json?q=python%20pandas'
#通过request请求获取数据
data=json.loads(requests.get(url).text)
#将所有data数据存到tweets集合
for tweet in data['results']:
tweets.save(tweet)
#将tweets集合中取出我发的tweet
res=tweets.find({'from_user','宋亚翔'})
print(res)

数据规整化(清理/转换/合并/重塑)

合并数据集

三种合并方法

1
2
3
1.pandas.merge 根据1个/多个键将不同的DataFrame中的行连接起来(像极了数据库连接操作 选几个行)
2.pandas.concat 沿着一条轴将多个对象堆叠在一起
3.实例方法combine_first 将重复数据编接在一起(像数据库的全外连接--先从第一个对象中选值,不行再去第二个对象中选值)

DataFrame的合并(merge和join)

merge函数参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import pandas as pd
from pandas import Series,DataFrame

#1.多对一的合并merge
##1.两个对象的列名相同
df1=DataFrame({'key':['b','b','a','c','a','a','b'],
'data1':range(7)
})
df2=DataFrame({'key':['a','b','d'],
'data2':range(3)
})
###多对一的合并 merge
print(pd.merge(df1,df2)) # 只有a和b
print(pd.merge(df1,df2,on='key')) #显示指定根据key 只有a和b

##2.两个对象的列名不同(分别指定 left_on=xxx,rigt_on=xxx)
df3=DataFrame({'lkey':['b','b','a','c','a','a','b'],
'data1':range(7)
})
df4=DataFrame({'rkey':['a','b','d'],
'data2':range(3)
})
###多对一的合并 merge
print(pd.merge(df3,df4,left_on='lkey',right_on='rkey')) #左边根据lkey 右边根据rkey

##3.外连接求取(键的并集)
print(pd.merge(df1,df2,how='outer'))

#2.多对多的合并(行的笛卡尔积)
df5=DataFrame({'key':['b','b','a','c','a','b'],
'data1':range(6)
})
df6=DataFrame({'key':['a','b','a','b','d'],
'data2':range(5)
})
#左边有个3个b,右边有2个b 所以最终结果有6个b行
print(pd.merge(df5,df6,on='key',how='left'))
print(pd.merge(df5,df6,how='inner'))

索引上的合并(merge和join只不过更改属性)

1
2
1.普通索引: 设置left_index或者right_index=True表明索引作为连接键
2.层次化索引:设置列表的形式合并键的多个列 (left_on=['key1','key2',right_index=True])

代码举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
from pandas import Series,DataFrame
# key value
#0 a 0
#1 b 1
#2 a 2
#3 a 3
#4 b 4
#5 c 5
# group_val
#a 3.5
#b 7.0

left1=DataFrame({'key':['a','b','a','a','b','c'],
'value':range(6)
})
right1=DataFrame({'group_val':[3.5,7]},
index=['a','b']
)
#根据左边key和右边的索引作为键(index key group_val)
print(pd.merge(left1,right1,left_on='key',right_index=True))

轴向连接(concat)

concat函数参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#随机生成3*4的数列
arr=np.arange(12).reshape((3,4))
print(np.concatenate([arr,arr],axis=1))

#假设有三个没有重叠索引的Series --> concat函数
s1=Series([0,1],index=['a','b'])
s2=Series([2,3,4],index=['c','d','e'])
s3=Series([5,6],index=['f','g'])
#(默认)concat是在axis=0上工作 --> 产生一个新的Series
# concat是在axis=1上工作 --> 产生一个新的DataFrame
print(pd.concat([s1,s2,s3]))
print(pd.concat([s1,s2,s3],axis=1)) #axis=1是列 0 1 2分别表示的s1 s2 s3

#a 0
#b 5
#f 5
#g 6
s4=pd.concat([s1*5,s3])
print(pd.concat([s1,s4],axis=1)) #axis=1是列 0 1分别是s1 s4
#传入innner可以得到他们的交集
print(pd.concat([s1,s4],axis=1,join='inner')) #axis=1是列 0 1分别是s1 s4 --> 交集就取前两行
#指定要在其他轴上使用的索引(join_axes参数) (使用指定索引 --> 可能会出现都是NaN值)
print(pd.concat([s1,s4],axis=1,join_axes=[['a','c','b','e']]))

#生成层次化索引(keys参数)

# one a 0
# b 1
# two a 0
# b 1
# three f 5
# g 6
# dtype: int64
res=pd.concat([s1,s1,s3],keys=['one','two','three']) #keys就是行
print(res)

# one two three
#a 0.0 0.0 NaN
#b 1.0 1.0 NaN
#f NaN NaN 5.0
#g NaN NaN 6.0
res1=pd.concat([s1,s1,s3],axis=1,keys=['one','two','three']) #keys就是列(axis=1生成一个DataFrame)
print(res1)

重叠数据的合并(combine_first)

方法总结

1
2
3
1. numpy中的where方法
2. Series中的combine_first方法
3. DataFrame中的combine_first方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
# a b
#f NaN f 0.0
#e 2.5 e 1.0
#d NaN d 2.0
#c 3.5 c 3.0
#b 4.5 b 4.0
#a NaN a NaN
a=Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],
index=['f','e','d','c','b','a'])
b=Series(np.arange(len(a),dtype=np.float64),
index=['f','e','d','c','b','a'])
b[-1]=np.nan #b中最后一个赋值NaN
print(a)
print(b)

#使用numpy中的where方法连接
print(np.where(pd.isnull(a),b,a))

#Series中的combine_first方法【+数据对齐】
print(b[:2].combine_first(a[2:]))

重塑(reshape)和轴向旋转(pivot)

1
2
1.重塑 reshape方法
2.轴向旋转 pivot方法

重塑层次化索引(stack和unstack)

1
2
1.stack: 将数据的列"旋转"为行  【列-->行】
2.unstack:将数据的行“旋转”为列 【行-->列】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#number one two three
#state
#Ohio 0 1 2
#Colorado 3 4 5
data=DataFrame(np.arange(6).reshape((2,3)),
index=pd.Index(['Ohio','Colorado'],name='state'), #索引有2个Ohio Colorado
columns=pd.Index(['one','two','three'],name='number') #列有三个one two three
)
#列转成行(默认操作是最内层)
res=data.stack() #变成一列0 1 2 3 4 5
print(res)

#行转成列(默认操作是最内层)
print(res.unstack()) #可以传入 分层级别的编号/分层级别的名称

长格式–> 宽格式

概述

1
1.时间序列数据[长格式(long)/堆叠格式(stacked)]存储在数据库和CSV

数据转换

移除重复数据(duplicated和drop_duplicataes)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

import pandas as pd
import numpy as np
from pandas import Series,DataFrame
# k1 k2
#0 one 1
#1 one 1
#2 one 2
#3 two 3
#4 two 3
#5 two 4
#6 two 4
data=DataFrame({'k1':['one']*3+['two']*4,
'k2':[1,1,2,3,3,4,4]
})
#1.一个列
#DataFrame的duplicated方法 --> 布尔型Series (各行是否是重复行)
print(data.duplicated())
#DataFrame的drop_duplicataes方法 -->移除了重复行的DataFrame
print(data.drop_duplicates())

#2.多个列
data['v1']=range(7) #多加一个列v1 有0-6这7个值
print(data.drop_duplicates(['k1'])) #只根据k1去判断

#3.duplicated和drop_duplicates 默认保留第一个出现的值组合
#keep='last'则保留最后一个
print(data.drop_duplicates(['k1', 'k2'],keep='last')) #更改keep让最后一个保留

利用函数/映射进行数据转换(Series的map方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#有关肉类的数据 食物 -- 盎司
data=DataFrame({'food':['bacon','pulled pork','bacon','Pastrami','corned beef','Bacon','pastrami','honey ham','nova lox'],
'ounces':[4,3,12,6,7.5,8,3,5,6]
})
print(data)

#想添加一列表示肉类食物来源的动物类型
#编写一个映射(肉类--动物)
meat_to_animal={
'bacon':'pig',
'pulled pork':'pig',
'pastrami':'cow',
'corned beef':'cow',
'honey ham':'pig',
'nova lox':'salmon',
}

#Series的map方法(接受一个函数/含有映射关系的字典型对象)
data['animal']=data['food'].map(str.lower).map(meat_to_animal)
print(data)

替换值(replace方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#0 1.0
#1 -999.0
#2 2.0
#3 -999.0
#4 -1000.0
#5 3.0
data=Series([1.,-999.,2.,-999.,-1000,3.])
print(data)
#-999可能是一个缺失数据的标记值 --> 更改为pandas可以理解的NA值
#一对一替换
data.replace(-999,np.nan)
#多对一替换
data.replace([-999,-1000],np.nan)
#多对多替换
data.replace([-999,-1000],[np.nan,0])
#多对多替换(字典形式)
data.replace({-999:np.nan,-1000:0})
print(data)

轴索引重命名(map全体更新和rename全体更新/部分更新)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
# one two three four
#Ohio 0 1 2 3
#Colorado 4 5 6 7
#New York 8 9 10 11

#Series轴标签和Series值都可以通过函数/映射 --> 新对象
data=DataFrame(np.arange(12).reshape((3,4)),
index=['Ohio','Colorado','New York'],
columns=['one','two','three','four'])

#轴标签也有map方法
print(data.index.map(str.upper)) #所有轴更大
data.index=data.index.map(str.upper)
#更新之后的data (标签更新)
print(data)

#rename方法
#创建数据集的转换版(不修改原始数据)
print(data.rename(index=str.title,columns=str.upper))
#部分轴标签更新
print(data.rename(index={'OHIO':'哈尔滨'},columns={'three':'第三'})) #替换
#原地修改(inplace=True)
datares=data.rename(index={'OHIO':'哈尔滨'},columns={'three':'第三'},inplace=True)

离散化和面元(bin)划分(cut函数和qcut)

cut函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
ages=[20,22,25,27,21,23,37,31,61,45,41,32]
#将数据划分为好几个面元(bin)
#使用pandas的cut函数
bins=[18,25,35,60,100] #划分为 18-25 26-35 35-60 60-100
cats=pd.cut(ages,bins)

#pandas返回的是一个特殊的Categorical对象【表示面元名称的字符串】
print(cats)

#一个表示不同分类名称的levels数组
#一个为年龄数据进行标号的labels实行
print(cats.codes)
print(pd.value_counts(cats)) #圆括号表示开端 方括号表示闭端 --> 可以通过right=False修改哪边是闭端

qcut函数

1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#cut和qcut都可以根据数据的最小值和最大值计算等长面元
#cut可能无法使得每个面元中含有相同数量的数据点
#qcut使用的样本分位数 --> 大小基本相等的面元

#正态分布
data=np.random.randn(1000)
cats=pd.qcut(data,4) #按照四位数进行切割
print(cats)
print(pd.value_counts(cats)) #圆括号表示开端 方括号表示闭端 --> 可以通过right=False修改哪边是闭端

异常值(检测和过滤)

1
2
3
4
5
6
7
8
9
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
np.random.seed(12345)
data=DataFrame(np.random.randn(1000,4))
print(data.describe())
#找到某列中|值|>3
flag=data[3]
print(flag[np.abs(flag)>3])

排列(np.random.permutation)和随机采样(np.random.randint)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#利用numpy.random.permutation函数 --> 对Series/DataFrame的列的排列工作 (permuting,随机重排序)
#通过需要排列的轴的长度调用permutation --> 整数数组(表示新序列)
# 0 1 2 3
#0 0 1 2 3
#1 4 5 6 7
#2 8 9 10 11
#3 12 13 14 15
#4 16 17 18 19
df=DataFrame(np.arange(5*4).reshape(5,4)) #生成5行4列的矩阵
sampler=np.random.permutation(5) #调用permutation(5)
print(sampler) #产生一个表示新顺序的整数数组
#基于ix索引操作 / take函数
print(df.take(sampler))

bag=np.array([5,7,-1,6,4])
sampler1=np.random.randint(0,len(bag),size=10) #0-5之间的10个数字
print(sampler1)
print(bag.take(sampler1))

指标/哑变量(get_dummies方法)

1
2
1.分类变量(categorical variable) --> 哑变量矩阵(dummy matrix)/指标矩阵(indicator matrix)
2.如果DataFrame的某一列中含有k个不同的值 -->一个k列矩阵/DataFrame(值全为0/1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
# data1 key
#0 0 b
#1 1 b
#2 2 a
#3 3 c
#4 4 a
#5 5 b
df=DataFrame({'key':['b','b','a','c','a','b'],
'data1':range(6)
})
#根据key列得到一个k列矩阵/DataFrame(全为1/0)
print(pd.get_dummies(df['key'])) #key取值有a b c 所以新的DataFrame列就是a b c

#给指标DataFrame的列加上一个前缀 --> get_dummies的prefix参数
dummies=pd.get_dummies(df['key'],prefix='xin') #key取值有a b c 所以新的DataFrame列就是xin_a xin_b xin_c
df_with_dummy=df[['data1']].join(dummies) #列就加入data1 成为四列
print(df_with_dummy)

字符串操作

字符串对象方法

py内置的字符串方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#val是要判断的字符串
val='a,b guido'

#1.字符串拆分
##根据split拆分成数段(用逗号分隔的字符串)
print(val.split(','))
##根据strip修剪空白符(包括换行符)
pieces=[x.strip() for x in val.split(',')]
print(pieces)

#2.字符串添加
##子字符串添加‘::’ --> .join()
print('::'.join(pieces))

#3.字符串查找
##子串定位 --> in关键字(index和find)
print('guido' in val)
##find和index区别[如果找不到的话index引发一个异常,find返回-1]
print(val.index(','))
print(val.find(':'))

#4.字符串统计
##返回指定子串的出现次数:
print(val.count(','))

正则表达式(regex)

1
2
3
4
5
1.py内置的re模块负责对字符串应用正则表达式
2.py内置的re模块分为三大类:
2.1 模式匹配
2.2 替换
2.3 拆分

pandas中矢量化的字符串函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
#清理待分析的散乱数据 --> 字符串规整化工作

#Dava dava@google.com
#Rob rob@gmail.com
#Steve steve@email.com
#Wes NaN
data={'Dava':'dava@google.com',
'Steve':'steve@email.com',
'Rob':'rob@gmail.com',
'Wes':np.nan}
#将data数据Series规格化
data=Series(data)
#判断data是否为空
print(data.isnull())

#通过data.map可以让所有的字符串和正则表达式方法都应用于各个值(如果存在NA就会报错!!!)
#Series有一些可以跳过NA值的字符串操作方法 --> 通过Series的str属性就可以访问这些方法
print(data.str.contains('gmail'))

绘图和可视化(matplotlib)

matplotlib API入门

1
2
3
4
5
6
7
8
9
1.matplotlib是一个用于创建出版质量图表的桌面绘图包(主要是2D方面)
2.matplotlib结合一种GUI工具包(IPython)可以拥有缩放和平移等交互功能
3.matplotlib支持各种操作系统上许多不同的GUI后端,而且将图片导出为各种常见的矢量(vector)和光栅图(raster):PDF,SVG,JPG,PNG,BMP,GIF等

使用方法:
1.Pylab模式的IPython(ipython--pylab) --> 将IPython配置为使用你所指定的matplotlib GUI后端(TK,wxPyhton,PyQt,Mac OS X native,GTK)
2.引入语句:
import matplotlib
import matplotlib.pyplot as plt

Figure和Subplot(更方便的plt.subplots方法)

旧的figure和subplot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn
fig=plt.figure()
#返回的对象是AxesSubplot对象 --> 直接调用实例方法就可以在其他空着的格子里面画画
ax1=fig.add_subplot(2,2,1) # 图像应该是2*2 并且 当前选中的是4个subplot中的第一个(编号从1开始)
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
#绘图命令(在最后一个用过的subplot进行绘制)
plt.plot(randn(50).cumsum(),'k--') #k--是一个线型选择(用于告诉matplotlib绘制黑色虚线图)
_=ax1.hist(randn(100),bins=20,color='k',alpha=0.3)
ax2.scatter(np.arange(30),np.arange(30)+3*randn(30))
plt.show()

新的subplots

1
2
3
4
5
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
#更方便的plt.subplots()方法
fig,axes=plt.subplots(2,3) # --> 一个含有已创建的subplot对象的NumPy数组

调整subplot周围的间距(Figure的subplots_adjust方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
	# wspace和hspace用于控制宽度和高度的百分比(用作subplot之间的间距)
1.subplots_adjust(left=None,bottom=None,right=None,top=None,wspace=None,hspace=None)
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn
# subplots为2行2列 使用相同的X和Y轴刻度
fig,axes=plt.subplots(2,2,sharex=True,sharey=True)
for i in range(2):
for j in range(2):
axes[i,j].hist(randn(500),bins=50,color='k',alpha=0.5)
#间距收缩为0
plt.subplots_adjust(wspace=0,hspace=0)
plt.show()

颜色(color)、标记(marker)、线型(linestyle)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn
#标记类型和线型必须放在颜色后面

#两种书写方式相同
#ax.plot(x,y,'g--') 在一个字符串中指定颜色和线型的方式非常方便
#ax.plot(x,y,linestyle='--',color='g')

#两种书写方式相同
plt.plot(randn(30).cumsum(),'ko--')
#plt.plot(randn(30).cumsum(),color='k',linestyle='dashed',marker='o') #marker是标记

#线形图(非实际数据点默认是按线性方式插值的) -- drawstyle选项修改
plt.plot(randn(30),'k--',label='Default')
plt.plot(randn(30),'k--',drawstyle='steps-post',label='steps-post')
plt.show()

刻度(xticks)、标签(xticklabels)、图例(xlim)

1
2
3
4
5
大多数的图表装饰项:	
1.过程型的pyplot接口(交互式使用) -- xlim(图表的范围)/xticks(刻度位置)/xticklabels(刻度标签)之类的方法
1.1 调用时不带参数(返回当前的参数值): 例如plt.xlim()返回当前的X轴绘图范围
1.2 调用时带参数(设置参数值): 例如plt.xlim([0,10])会将X轴的范围设置0-10
2.面向对象的原生matplotlib API

设置标题(set_title)、轴标签(set_xlabel)、刻度(set_xticks)、刻度标签(set_xticklabels)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn
fig=plt.figure();
ax=fig.add_subplot(1,1,1)
ax.plot(randn(1000).cumsum())

#修改X轴的刻度 --> set_xticks和set_xticklabels
#set_xticks告诉matplotlib要将刻度放在数据范围中的哪些位置(默认情况下这些位置也是刻度标签)
#set_xticklabels将任何其他的值用作标签
ticks=ax.set_xticks([0,250,500,750,1000])
labels=ax.set_xticklabels(['one','two','three','four','five'],rotation=30,fontsize='small')

#给X轴设置名称 --> set_xlabel
#给设置一个标题 --> set_title
ax.set_title('My first matplotlib plot')
ax.set_xlabel('Stages')
plt.show()

添加图例(ax.legend/plt.legend)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn

fig=plt.figure();ax=fig.add_subplot(1,1,1)
#画三条线段
ax.plot(randn(100).cumsum(),'k',label='one')
ax.plot(randn(100).cumsum(),'k',label='two')
ax.plot(randn(100).cumsum(),'k',label='three')
#调用ax.legnd()或plt.legend()来自动创建图例
ax.legend(loc='best')
plt.show()

注解以及在Subplot上绘图(matplotlib.pyplot/matplotlib.patches)

1
2
3
1.matplotlib有一些表示常见图形的对象(对象被称为块[patch])
2.matplotlib.pyplot(Rectangle和Circle)
3.matplotlib.patches
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn
from datetime import datetime
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
rect=plt.Rectangle((0.2,0.75),0.4,0.15,color='k',alpha=0.3)
circ=plt.Circle((0.7,0.2),0.15,color='b',alpha=0.3)
pgon=plt.Polygon([[0.15,0.15],[0.35,0.4],[0.2,0.6]],color='g',alpha=0.5)
ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)
plt.show()

将图标保存到文件(plt.savefig)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from datetime import datetime
from io import BytesIO
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
rect=plt.Rectangle((0.2,0.75),0.4,0.15,color='k',alpha=0.3)
circ=plt.Circle((0.7,0.2),0.15,color='b',alpha=0.3)
pgon=plt.Polygon([[0.15,0.15],[0.35,0.4],[0.2,0.6]],color='g',alpha=0.5)
ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)

#将当前图标保存到文件 <--> Figure对象的实例方法savefig
##普通格式(指定扩展名是什么就会出现什么)
plt.savefig('figpath.svg') #图表保存为SVG文件
##自带各种属性
plt.savefig('figpath.png',dpi=400,bbox_inches='tight')
##Web上提供动态生成的图片
buffer=BytesIO()
plt.savefig(buffer)
plot_data=buffer.getvalue()

matplotlib配置

1
2
3
4
5
6
 操作matplotlib配置系统的方式
1.Python编程方式(利用rc方法):
1.1 plt.rc('figure',figsize=(10,10)) #第一个参数是希望自定义的对象
1.2 font_options={'family':'monospace','weight':'bold','size':'small'}
plt.rc('font',**font_options) #将选项写成一个字典
2.进入matplotlib/mpl-data目录 --> 自定义

pandas中的绘图函数

线型图(默认kind=’line’)

1
1.Series和DataFrame都有一个用于生成各类图表的plot方法(默认是线形图)

Series的plot参数:

DataFrame的plot参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn
s=Series(np.random.randn(10).cumsum(),index=np.arange(0,100,10)) #该Series对象的索引会被传给matplotlib --> 绘制X轴
s.plot()
plt.show()
#DataFrame的plot方法会在一个subplot中为各列绘制一条线,并自动创建图例
df=DataFrame(np.random.randn(10,4).cumsum(0),columns=['A','B','C','D'],index=np.arange(0,100,10))
df.plot()
plt.show()

柱状图(kind=’bar’/‘barh’)

1
2
1.Series.plot( 设置kind='bar'(垂直柱状图) / kind='barh'(水平柱状图) )
2.DataFrame.plot( 设置kind='bar'(垂直柱状图) / kind='barh'(水平柱状图) )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
from pandas import Series,DataFrame
import matplotlib
import matplotlib.pyplot as plt
from numpy.random import randn

#Series
fig,axes=plt.subplots(2,1)
data=Series(np.random.rand(16),index=list('abcdefghijklmnop'))
#kind='bar'
data.plot(kind='bar',ax=axes[0],color='k',alpha=0.7) #alpha是透明度0-1
data.plot(kind='barh',ax=axes[0],color='k',alpha=0.7) #alpha是透明度0-1
plt.show()

#DataFrame(柱状图会将每一行的值分为一组)
df = pd.DataFrame(np.random.rand(6, 4),
index=['one', 'two', 'three', 'four', 'five', 'six'],
columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus'))
df.plot(kind='bar')
plt.show()

#stacked=True可以生成堆积柱状图
df.plot(kind='barh',stacked=True,alpha=0.5)
plt.show()

直方图(Series的hist方法)和密度图(kind=’kde’)

1
2
1.直方图(histogram):是一种可以对值频率进行离散化显示的柱状图[数据点被拆分到离散的、间隔均匀的面元中,绘制的是各面元中数据点的数量]
2.密度图(KDE,核密度估计图):将该分布近似为一组核(诸如正态分布等)
1
2
3
tips['tip_pct']=tips[tip] / tips['total_bill']
tips['tip_pct'].hist(bins=50)
tips['tip_pct'].plot(kind='kde')

散布图(plt.scatter方法和pd.scatter_matrix函数)

1
2
3
4
5
1.散布图(scatter plot):是观察两个一维数据序列之间的关系
2.使用方法
2.1 plt.scatter() 观察一组变量的散布图(也被称为散布图矩阵)
2.2 pd.scatter_matrix()
pandas提供了一个从DataFrame创建散布图矩阵的scatter_matrix函数(还支持在对角线上放置各变量的直方图/密度图)

Python图形化工具生态系统

1
2
1.Chaco: 静态图+交互式图形
2.mayavi:基于开源C++图形库VTK的3D图形工具包

数据聚合与分组运算

GroupBy技术

1
2
3
4
5
6
7
8
9
1.分组(split) : pandas对象(Series/DataFrame) --> 根据一个/多个键拆分(split)为多组 [对象特定轴上执行的,DataFrame可以在其行(axis=0)其列(axis=1)进行分组]
1.1 分组键:(多种形式+类型不必相同)
1.1.1 列表/数组(长度和待分组的轴一样)
1.1.2 表示DataFrame某个列名的值
1.1.3 字典/Series(待分组轴上的值--分组名的对应关系)
1.1.4 函数(用于处理轴索引/索引中的各个标签)

2.应用(apply) : 将一个函数应用到各个分组 --> 产生一个新值
3.合并(combine) : 所有函数的执行结果合并到最终的结果对象中

流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

#1.分组键为Series
df=DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)})
#根据一个分组
##根据key1进行分组,并计算data1列的平均值 --> 访问data1,并且根据key1调用groupby
grouped1=df['data1'].groupby(df['key1']) #grouped是一个GroupBy对象
##调用GroupBy的mean方法计算分组平均值
print(grouped1.mean())
print()

#根据多个分组
grouped2=df['data1'].groupby([df['key1'],df['key2']])
##调用GroupBy的mean方法计算分组平均值
print(grouped2.mean())
print()

#2.分组键为数组(长度适当)
states=np.array(['Ohio','California','California','Ohio','Ohio'])
years=np.array([2005,2005,2006,2005,2006])
grouped3=df['data1'].groupby([states,years])
print(grouped3.mean())
print()

#3.分组键为列名(字符串/数字/其他Python对象)
print(df.groupby('key1').mean())
print(df.groupby(['key1','key2']).mean())
print()

分组迭代(groupby方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
	1.GroupBy对象支持迭代 --> 一组二元元组(分组名+数据块)

import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn
# data1 data2 key1 key2
#0 0.794423 0.872517 a one
#1 0.228070 0.846891 a two
#2 1.002588 0.632977 b one
#3 -1.664231 0.320534 b two
#4 1.470316 -1.338423 a one
df=DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)
})

for name,group in df.groupby('key1'): #根据key1进行分组输出name是a的和group是b的
print(name)
print(group)

print("--------------------------------")

for (k1,k2),group in df.groupby(['key1','key2']): # 多重键(元组的第一个元素将会是由键值组成的元组) # a与one a与two b与one b与two
print(k1,k2)
print(group)

print("--------------------------------")

#将这些数据片段做成一个字典
pieces=dict(list(df.groupby('key1')))
print(pieces['b'])

print("--------------------------------")

#groupby默认是axis=0按照行分组
grouped1=df.groupby(df.dtypes,axis=1)
pieces2=dict(list(grouped1))
print(pieces2)

执行结果:

选取一个/一组列(groupby([‘x1’,’x2’]))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#两种转换
df.groupby('key1')['data1'] <--> df['data1'].groupby(df['key1'])

import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn
#对于由DataFrame产生的GroupBy对象 --> 用一个/一组列名对其进行索引(选取部分列进行聚合的目的)
# data1 data2 key1 key2
#0 0.794423 0.872517 a one
#1 0.228070 0.846891 a two
#2 1.002588 0.632977 b one
#3 -1.664231 0.320534 b two
#4 1.470316 -1.338423 a one
df=DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)
})
res=df.groupby(['key1','key2'])[['data2']].mean() #df['data2'].groupby(df['key1','key2'])
print(res)

通过字典/Series进行分组(groupby(字典名))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

#1.DataFrame
people = pd.DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
#添加几个NaN值
people.ix[2:3,['b','c']]=np.nan # b和c两列的第三行Wes
#假设已知列的分组关系(根据分组计算列的总计)
mapping={'a':'red','b':'red','c':'blue','d':'blue','e':'red','f':'orange'}
#只需将这个字典传给groupby
by_column=people.groupby(mapping,axis=1) #传入分组字典和按照列分组
print(by_column.sum())

#2.Series(可以看做一个固定大小的映射)
map_series=Series(mapping)
by_column2=people.groupby(map_series,axis=1)
print(by_column2.count())

通过函数进行分组(groupby(函数))

1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

people = pd.DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
#添加几个NaN值
people.ix[2:3,['b','c']]=np.nan # b和c两列的第三行Wes
#传入len函数
print(people.groupby(len).sum())

通过索引级别分组(level关键字)

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

Icolumns = pd.MultiIndex.from_arrays([['US', 'US', 'US', 'JP', 'JP'],
[1, 3, 5, 1, 3]],
names=['cty', 'tenor'])
hier_df=DataFrame(np.random.randn(4,5))
print(hier_df)
#通过level关键字传入级别编号/名称
res=hier_df.groupby(level='cty',axis=1)
print(res.count())

数据聚合

groupby聚合函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

#quantile可以计算Series/DataFrame列的样本分位数
df=DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)
})
#根据key1分组
grouped=df.groupby('key1')
print(grouped['data1'].quantile(0.9)) #quantile是一个Series方法

无索引的形式返回聚合数据(as_index=False禁用)

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

#quantile可以计算Series/DataFrame列的样本分位数
df=DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)
})
#根据key1和Key2分组 但是以"无索引化"
print(df.groupby(['key1','key2'],as_index=False).mean())

分组级运算和转换

transform和apply

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

people = pd.DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
key=['one','two','one','two','one']

#1.根据transform() --> 1.产生一个可以广播的标量值(np.mean) 2.产生一个相同大小的结果数组
print(people.groupby(key).mean()) #列是a b c d e 行是one two
print("---------------------------------------")
print(people.groupby(key).transform(np.mean)) #列是a b c d e 行是Joe

禁止分组键(group_keys=False)

1
data.groupby('key1',group_keys=False).apply(top)

分位数(quantile)和桶(bucket)分析

1
2
3
1.pandas有一些能根据指定面元/样本分位数-->数据拆分为多块的工具(cut和qcut)
2.groupby
1和2结合起来 --> 桶(bucket)和分位数(quantile)

两种不同的分别方法(cut和qcut):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn
frame=DataFrame({
'data1':np.random.randn(1000),
'data2':np.random.randn(1000)
})

#1.长度相等的桶 -- 区间大小相等(data1相同) -- cut()
##按照四位数进行分隔
factor=pd.cut(frame.data1,4) #cut返回的Factor对象可以直接用于groupby
##统计计算
def get_stats(group): # 定义函数get_stats(4个方法)
return {'min':group.min(),
'max':group.max(),
'count':group.count(),
'mean':group.mean()
}
grouped1=frame.data2.groupby(factor)
print(grouped1.apply(get_stats).unstack()) # 重塑层次化索引 --> unstack()是行转成列(默认操作是最内层)

#2.大小相等的桶 -- 数据点数量相等(count相同) -- qcut()
##按照10位数分隔 + labels=False
grouping=pd.qcut(frame.data1,10,labels=False)
##统计计算
grouped2=frame.data2.groupby(grouping)
print(grouped2.apply(get_stats).unstack())

(示例)用特定于分组的值填充缺失值(fillna方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

#对于缺失数据的清理工作 --> 1.dropna()将其滤除 2.fillna()将其填充

##获取一个Series对象
s=Series(np.random.randn(6))
s[::2]=np.nan #索引为0 2 4三行设置NaN值
print(s)
print("---------------------------------")
#使用fillna()填充所有的NaN值
print(s.fillna(s.mean())) #mean是算数平均值

(示例)随机采样和排列(random.permutation方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from numpy.random import randn

#蒙特卡罗模拟(大数据集中随机抽取样本) --> np.random.permutation(N)的前K个元素 [N为完整数据的大小,k为期待的样本大小]
#构造一副英语型扑克牌
#红桃(Hearts) 黑桃(Spades) 梅花(Clubs) 方片(Diamonds)
suits=['H','S','C','D']
card_val=(range(1,11)+[10]*3)*4
base_names=['A']+range(2,11)+['J','K','Q']
cards=[]
for suit in ['H','S','C','D']:
cards.extend(str(num)+suit for num in base_names)
#拥有一个长度为52的Series(索引为牌名) -- 值则是21点/其他游戏中用于计分的点数(A的点数为1)
deck=Series(card_val,index=cards)
print(np.random.permutation(len(deck)))

透视表(pivot table)和交叉表(crosstab)

pivot_table参数:

1
2
3
4
5
6
7
8
9
 透视表:
1.透视表(pivot table):是各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具
2.透视表通过一个/多个键对数据进行聚合,并根据行和列上的分组键将数据分配到各个矩阵区域
3.DataFrame有一个pivot_table方法 【还可以添加分项小计margins】
4.pandas.pivot_table函数
交叉表:
1.交叉表:是一种用于计算分组频率的特殊透视表
2.DataFrame有一个pivot_table方法
3.pandas.crosstab函数(数组/Series/数组列表,数组/Series/数组列表,...)

时间序列(time series)

1
2
3
4
5
 具体应用场景:
1.时间戳(timestamp):特定的时刻
2.固定时期(period):例如2022年9月
3.时间间隔(interval):由起点和结束时间戳表示
4.实验/过程时间:每个时间点都是相对于特定起始时间的一个度量

日期和时间数据类型及工具(datetime模块)

1
2
1.python标准库:日期(data)、时间(time)数据的数据类型、日历方面的功能
2. datetime模块 time模块 calendar模块

datetime模块中的数据类型

1
2
3
4
5
import datetime
#获取当前时间now
now=datetime.datetime.now() # 2022-09-16 14:33:42.323779
print(now)
print(now.year,now.month,now.day)

字符串和datetime之间的转换(strptime/strftime方法)

datetime格式定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import datetime
from dateutil.parser import parse
import pandas as pd
#(-->传入一个格式化字符串)利用 str/strftime方法
#datetime对象和pandas的Timestamp对象可以被格式化字符串

##三种方式:
#1.利用datetime.strftime方法(将字符串转为日期)
print(datetime.datetime(2011,1,3).strftime('%Y-%m-%d')) #%Y是四位数的年 m是2位数的月(01-12) d是2位数的日(01-31)
#2.利用datetime.strptime方法(通过已知格式进行日期解析的最佳方式)
value='2011-01-03'
print(datetime.datetime.strptime(value,'%Y-%m-%d'))
#3.通过dateutil第三方包的parser.parse方法
print(parse('2011-01-03'))
print(parse('6/12/2011',dayfirst=True)) #通常日出现在月前面 (年 日 月) --> 设置dayfirst=True

datestrs=['7/6/2011','8/6/2011']
##to_datetime方法 (解析多种不同的日期表示形式)
print(pd.to_datetime(datestrs)) #to_datetime方法
#处理缺失值(None/空字符串)
print(pd.to_datetime(datestrs+[None])) #NaT(Not a Time)是pandas中时间戳数据的Na值

时间序列基础

索引更换为datetime数据

1
2
3
4
5
6
7
8
9
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd

dates=[datetime.datetime(2011,1,2),datetime.datetime(2011,1,5),datetime.datetime(2011,1,7),datetime.datetime(2011,1,8),datetime.datetime(2011,1,10),datetime.datetime(2011,1,12)]
#根据dates给出的时间作为索引
ts=Series(np.random.randn(6),index=dates) #datetime对象实际上是放在一个DatatimeIndex中
print(ts)

索引、选取、子集构造(和Series一致)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd

dates=[datetime.datetime(2011,1,2),datetime.datetime(2011,1,5),datetime.datetime(2011,1,7),datetime.datetime(2011,1,8),datetime.datetime(2011,1,10),datetime.datetime(2011,1,12)]
#根据dates给出的时间作为索引
ts=Series(np.random.randn(6),index=dates) #datetime对象实际上是放在一个DatatimeIndex中
print(ts)

#TimeSeries是Series的一个子类(索引和数据选取方面行为一样)
#获取ts的第三行 (2011-01-07)
stamp=ts.index[2]
print(f'stamp抓取的是:{stamp}')
print(f'stamp对应行的数据是:{ts[stamp]}')

日期的范围/频率/移动

生成日期范围(pandas.data_range)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd

#(默认)date_range会产生按天计算的时间点
index1=pd.date_range('4/1/2012','5/1/2012') # 从2012年4月1日到2012年6月1日 dtype='datetime64[ns]', freq='D'
print(index1)
print("---------------------------------------------------------------------------")
#如果只传入起始/结束日期(start/end) --> 还得传入一个表示一段时间的数字(periods='x')
index2=pd.date_range(start='4/1/2012',periods=10)
print(index2)
print("---------------------------------------------------------------------------")
index3=pd.date_range(end='6/1/2012',periods=10)
print(index3)
print("---------------------------------------------------------------------------")

#只显示日期索引(只有每个月最后一天) --> 更改BM频率freq='BM'
index4=pd.date_range('1/1/2000','12/1/2000',freq='BM')
print(index4)
print("---------------------------------------------------------------------------")

#产生一组被规范化到午夜的时间戳() --> 更改normalize=True
index5=pd.date_range('5/2/2012',periods=10,normalize=True)
print(index5)

频率和日期偏移量(freq属性)

时间序列的基础频率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from pandas.tseries.offsets import Hour,Minute
#pandas中的频率=基础频率(字符串别名表示)+乘数
#对于每个基础频率,都有一个被称为日期偏移量(data offset)的对象与之对应

##1.比较笨重的方法
#按小时计算的频率(Hour类表示)
hour=Hour()
print(hour) #1 Hour
#定制偏移量的倍数(传入一个整数)
d_hour=Hour(4)
print(d_hour)

##2.比较方便的方法
#创建字符串别名
index1=pd.date_range('1/1/2000','2/1/2000',freq='4h') #按照4个小时进行变换
print(index1)

#大部分偏移量对象通过加法进行连接
print(f'加起来一共是:{Hour(2)+Hour(4)+Minute(30)}')

#freq='WOM-3FRI' --> "每月第三个星期五"之类的日期
index2=pd.date_range('1/1/2000','2/1/2000',freq='WOM-3FRI')
print(list(index2))

移动(超前和滞后)数据(shift方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from pandas.tseries.offsets import Hour,Minute

#Series和DataFrame都有一个shift方法(单纯的前移/后移操作,保持索引不变)
#2000-01-31 -0.201348
#2000-02-29 -0.126236
#2000-03-31 -0.457643
#2000-04-30 1.012834
ts=Series(np.random.randn(4),
index=pd.date_range('1/1/2000',periods=4,freq='M') # 从2000.01.01开始记录四个日期 然后频率为M(每月最后一个日历日)
)
print(ts)
print("---------------------------------------------------")
print(ts.shift(2)) # 日期不变 数据往后压(前面补NaN)
print("---------------------------------------------------")
print(ts.shift(-2)) # 日期不变 数据往前提(后面补NaN)
print("---------------------------------------------------")
print(ts.shift(3,freq='D')) # 日期根据频率D变化
print("---------------------------------------------------")

通过偏移量对日期进行位移(rollback和rollforward方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from pandas.tseries.offsets import Hour,Minute
from pandas.tseries.offsets import Day,MonthEnd

#pandas的日期偏移量可以作用在datatime/Timestamp对象上
now=datetime.datetime(2011,11,17) # 当前时间设定为2011年11月17日
print(now+3*Day()) # 加上三天之后成为2011年11月20日

#添加锚点偏移量(频率要考虑月末是不是周末,并不是均匀分隔的) --> 第一次增量会将原日期向前滚动到符合频率规则的下一个日期
print(now+MonthEnd()) # 2011年11月20日+月末=2011年11月30日
print(now+MonthEnd(2)) # 2011年11月20日+月末(往后推2个月)=2011年12月31日
#通过rollforward和rollback方法(显式将日期向前/向后滚动)
offset=MonthEnd()
print(f'现在是:{now}') # 2011年11月17日
print(offset.rollforward(now)) #往前推 日子快了 就是11.30日
print(offset.rollback(now)) #往后推 日子慢了 就是10.31日

时区处理(第三方库pytz)

1
2
1.在Python中时区信息来自第三方库pytz --> 使得Python可以使用Olson数据库(汇编了世界时区信息)
2. import pytz

pandas中的方法可以接受时区名(建议)/对象

1
2
3
4
5
import pytz
print(pytz.common_timezones[-5:]) #最后五个时区表
#获取时区对象 --> pytz.timezone
tz=pytz.timezone('US/Eastern')
print(tz)

本地化(tz_localize)和转换(tz_convert)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
import pytz

#(默认)pandas中的时间序列是单纯的(naive)时区
rng=pd.date_range('3/9/2012 9:30',periods=6,freq='D') # 从2012年9月3日9点30分开始 顺序出来6个日期
#随机出6个数字 索引按照rng的日期
ts=Series(np.random.randn(len(rng)),index=rng)
print(ts)
print(ts.index.tz) #None

#单纯到本地化的转换 --> tz_localize方法
ts_utc=ts.tz_localize('UTC')
print(ts_utc)

#转换到其他时区 --> tz_convert方法
ts_con=ts_utc.tz_convert('US/Eastern')
print(ts_con)

时期+算数运算(pd.Period类)

1
2
1.时期:时间区间(比如:数日,数月,数季,数年等)
2.Period类所表示的就是这种数据类型(构造函数需要用到一个字符串/整数)

Period类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
import pytz

#这个Period对象表示的是从2007年1月1日到2007年12月31日之间的整段时间
p=pd.Period(2007,freq='A-DEC')
#这个Period对象表示的是从2022年1月1日到2022年12月31日之间的整段时间
p2=pd.Period(2022,freq='A-DEC')
print(f'当前年份:{p}')
#只需要对Period对象加/减一个整数就可以达到根据其频率进行位移
print(f'当前年份基础上加五年:{p+5}')
print(f'当前年份基础上减两年:{p-2}')
print(f'两个相同频率的Period对象之间的差就是单位数量的差:{p2-p}') #2022-2007=15

时期的频率转换(asfreq方法)

1
2
3
4
5
6
7
8
9
10
import datetime
import pandas as pd

#这个Period对象表示的是从2007年1月1日到2007年12月31日之间的整段时间
p=pd.Period(2007,freq='A-DEC')

#任务:
#年度时期 --> 当年年初/年末的一个月度时期
print(p.asfreq('M',how='start'))
print(p.asfreq('M',how='end'))

通过数组创建PeriodIndex

1
index=pd.PeriodIndex(xxx,freq='Q-DEC')

重采样(resampling)+频率转换

1
2
3
重采样(resampling):将时间序列从一个频率 --> 另一个频率的处理过程
降采样(downsampling):高频率数据聚合 --> 低频率
升采样(upsampling):低频率数据 --> 高频率

重采样(resample方法)

resample方法的参数

1
2
3
4
5
6
7
8
9
10
11
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from numpy.random import randn

rng=pd.date_range('1/1/2000',periods=100,freq='D')
ts=Series(randn(len(rng)),index=rng)
print(ts.resample('M').mean()) #以前是resample('M',how='mean')
print("-------------------------------------------------------------------------")
print(ts.resample('M',kind='period').mean()) #聚合到时期(period)

降采样(resample方法更改属性)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from numpy.random import randn
import pytz

rng=pd.date_range('1/1/2000',periods=12,freq='T')
ts=Series(np.arange(12),index=rng) #索引是时间(从2000年1月1日开始每一分钟一个数据)
print(ts)
print("---------------------------------")
#1分钟聚合到5分钟(通过求和)
print(ts.resample('5min').sum()) # 默认是右区间闭合(X,X] 默认以各面元左边界的时间戳进行标记
print("---------------------------------")
print(ts.resample('5min',closed='left').sum()) # 可以通过closed改为是左区间闭合[X,X) 默认以各面元左边界的时间戳进行标记
print("---------------------------------")
print(ts.resample('5min',closed='left',label='right').sum()) # 可以通过closed改为是左区间闭合[X,X) 更改为以各面元右边界的时间戳进行标记
print("---------------------------------")

#对结果索引做一些位移 (loffset设置一个字符串/日期偏移量)
print(ts.resample('5min',loffset='-1s').sum())
print("---------------------------------")

OHLC降采样(属性how=’ohlc’)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from numpy.random import randn

#金融领域(有一种无处不在的时间序列聚合方式)
#计算各面元的四个值
##第一个值(open,开盘)
##最后一个值(close,收盘)
##最大值(high,最高)
##最小值(low,最低)
rng=pd.date_range('1/1/2000',periods=6,freq='T')
ts=Series(np.arange(6),index=rng) #索引是时间(从2000年1月1日开始每一分钟一个数据)
print(ts)
print("------------------------------------")
print(ts.resample('5min').ohlc())

groupby降采样(groupby加上lambda字符串)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from numpy.random import randn

rng=pd.date_range('25/1/2000',periods=13,freq='D')
ts=Series(np.arange(13),index=rng) #索引是时间(从2000年1月1日开始每一分钟一个数据)
print(ts)
print("--------------------------------------------------")

#根据月份/星期几进行分组
print(ts.groupby(lambda x:x.month).mean()) #根据月份
print("--------------------------------------------------")
print(ts.groupby(lambda x:x.weekday).mean()) #根据星期X

升采样和插值(fill_method属性和limit属性)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from numpy.random import randn

frame = pd.DataFrame(np.random.randn(2, 4),
index=pd.date_range('1/1/2000', periods=2,freq='W-WED'), #频率是周
columns=['Colorado', 'Texas', 'New York', 'Ohio'])
print(frame)
print("-----------------------------------------------------------------------------------------------------------------")

#将其重采样到日频率(默认会引入缺失值)
df_daily=frame.resample('D').sum()
print(df_daily)
print("-----------------------------------------------------------------------------------------------------------------")

#填充(fill_method属性)
print(frame.resample('D').ffill())
print("-----------------------------------------------------------------------------------------------------------------")
#填充指定的时期数
print(frame.resample('D').ffill(limit=2)) #前三行填充
print("-----------------------------------------------------------------------------------------------------------------")

通过时期进行重采样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import datetime
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
from numpy.random import randn

frame = pd.DataFrame(np.random.randn(24, 4),
index=pd.period_range('1-2000', '12-2001', freq='M'), #按照月从2000年1月到2001年12月一共24个
columns=['Colorado', 'Texas', 'New York', 'Ohio']) #列为四个项

#降采样(只有2000和2001行)
annual_frame=frame.resample('A-DEC').mean()
print(annual_frame)
print("----------------------------------------------------------------------------------")
#升采样(要决定在新频率中各区间的哪端用于放置原来的值)
print(annual_frame.resample('Q-DEC').ffill()) # Q-DEC是季度型(每年以12月结束)
print("----------------------------------------------------------------------------------")
print(annual_frame.resample('Q-DEC',convention='start').ffill()) # Q-DEC是季度型(每年以12月结束)
print("----------------------------------------------------------------------------------")

移动窗口函数

移动窗口和指数加权函数:

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. Numpy基础(数组和矢量计算)
    1. 1.1. 多维数组对象(ndarray)
      1. 1.1.1. 创建ndarray
      2. 1.1.2. ndarray数据类型
      3. 1.1.3. 数组和标量之间的运算
      4. 1.1.4. 基本的索引和切片
        1. 1.1.4.1. 一维数组
        2. 1.1.4.2. 高维数组
      5. 1.1.5. 切片索引
      6. 1.1.6. 布尔型索引
      7. 1.1.7. 花式索引
      8. 1.1.8. 数组转置和轴对称
        1. 1.1.8.1. reshape函数
        2. 1.1.8.2. 转置和轴对称函数
      9. 1.1.9. 通用函数(元素级数组函数)
      10. 1.1.10. 数组进行数据处理
      11. 1.1.11. 条件逻辑(数组运算)
      12. 1.1.12. 数学和统计方法
      13. 1.1.13. 布尔型数组的方法
      14. 1.1.14. 排序(sort方法)
      15. 1.1.15. 数组的集合运算
    2. 1.2. 数组的文件输入输出(文本/二进制数据)
      1. 1.2.1. 保存到磁盘(save和load)
      2. 1.2.2. 存取文本文件
    3. 1.3. 线性代数(linalg)
    4. 1.4. 随机数生成(random)
  2. 2. pandas入门
    1. 2.1. Series(像字典)
    2. 2.2. DataFrame(表格型)
      1. 2.2.1. DataFrame创建
      2. 2.2.2. DataFrame使用
    3. 2.3. 索引对象
    4. 2.4. 基本功能
      1. 2.4.1. 重新索引(reindex)
      2. 2.4.2. 丢弃指定轴上的项(drop)
      3. 2.4.3. 索引+选取+过滤
      4. 2.4.4. 算术运算和数据对齐
      5. 2.4.5. 函数应用和映射(apply和ufuns方法)
      6. 2.4.6. 排序和排名(sort_index和sorting)
      7. 2.4.7. 排名(rank)
      8. 2.4.8. 带有重复值的轴索引
      9. 2.4.9. 汇总和统计
        1. 2.4.9.1. 相关系数(corr)和协方差(cov)
        2. 2.4.9.2. 唯一值(unique)和值计数(value_counts)和成员资格(isin)
      10. 2.4.10. 处理缺失数据
      11. 2.4.11. 层次化索引
        1. 2.4.11.1. 重排分级顺序(sortlevel)
        2. 2.4.11.2. 根据级别汇总统计(groupby)
        3. 2.4.11.3. 使用DataFrame的列(set_index)
  3. 3. 数据(加载/存储/文件格式)
    1. 3.1. 读取数据(文本格式)
      1. 3.1.1. 读取函数介绍
      2. 3.1.2. 逐块读取文本文件(属性nrows和属性chunksize)
      3. 3.1.3. 数据写出到文本格式(to_csv)
      4. 3.1.4. 手工处理分隔符格式(csv.Dialect子类)
      5. 3.1.5. JSON数据(loads和dumps方法)
      6. 3.1.6. XML和HTML(get和text_content方法)
      7. 3.1.7. 解析XML(lxml.objectify)
    2. 3.2. 二进制数据格式(save和load方法)
    3. 3.3. HDF5格式(层次型数据格式HDFStore类)
    4. 3.4. 读取Microsoft Excel文件(ExcelFile类的xlrd和openpyxl包)
    5. 3.5. HTML和Web API(requests包)
    6. 3.6. 数据库()
      1. 3.6.1. 关系型数据库(pandas.io.sql模块的read_frame函数)
      2. 3.6.2. 非关系型数据库(MongoDB为例)
  4. 4. 数据规整化(清理/转换/合并/重塑)
    1. 4.1. 合并数据集
      1. 4.1.1. DataFrame的合并(merge和join)
      2. 4.1.2. 索引上的合并(merge和join只不过更改属性)
      3. 4.1.3. 轴向连接(concat)
      4. 4.1.4. 重叠数据的合并(combine_first)
    2. 4.2. 重塑(reshape)和轴向旋转(pivot)
      1. 4.2.1. 重塑层次化索引(stack和unstack)
      2. 4.2.2. 长格式–> 宽格式
    3. 4.3. 数据转换
      1. 4.3.1. 移除重复数据(duplicated和drop_duplicataes)
      2. 4.3.2. 利用函数/映射进行数据转换(Series的map方法)
      3. 4.3.3. 替换值(replace方法)
      4. 4.3.4. 轴索引重命名(map全体更新和rename全体更新/部分更新)
      5. 4.3.5. 离散化和面元(bin)划分(cut函数和qcut)
        1. 4.3.5.1. cut函数
        2. 4.3.5.2. qcut函数
      6. 4.3.6. 异常值(检测和过滤)
      7. 4.3.7. 排列(np.random.permutation)和随机采样(np.random.randint)
      8. 4.3.8. 指标/哑变量(get_dummies方法)
    4. 4.4. 字符串操作
      1. 4.4.1. 字符串对象方法
      2. 4.4.2. 正则表达式(regex)
      3. 4.4.3. pandas中矢量化的字符串函数
  5. 5. 绘图和可视化(matplotlib)
    1. 5.1. matplotlib API入门
      1. 5.1.1. Figure和Subplot(更方便的plt.subplots方法)
        1. 5.1.1.1. 旧的figure和subplot
        2. 5.1.1.2. 新的subplots
      2. 5.1.2. 调整subplot周围的间距(Figure的subplots_adjust方法)
      3. 5.1.3. 颜色(color)、标记(marker)、线型(linestyle)
      4. 5.1.4. 刻度(xticks)、标签(xticklabels)、图例(xlim)
        1. 5.1.4.1. 设置标题(set_title)、轴标签(set_xlabel)、刻度(set_xticks)、刻度标签(set_xticklabels)
        2. 5.1.4.2. 添加图例(ax.legend/plt.legend)
        3. 5.1.4.3. 注解以及在Subplot上绘图(matplotlib.pyplot/matplotlib.patches)
        4. 5.1.4.4. 将图标保存到文件(plt.savefig)
      5. 5.1.5. matplotlib配置
    2. 5.2. pandas中的绘图函数
      1. 5.2.1. 线型图(默认kind=’line’)
      2. 5.2.2. 柱状图(kind=’bar’/‘barh’)
      3. 5.2.3. 直方图(Series的hist方法)和密度图(kind=’kde’)
      4. 5.2.4. 散布图(plt.scatter方法和pd.scatter_matrix函数)
    3. 5.3. Python图形化工具生态系统
  6. 6. 数据聚合与分组运算
    1. 6.1. GroupBy技术
      1. 6.1.1. 分组迭代(groupby方法)
      2. 6.1.2. 选取一个/一组列(groupby([‘x1’,’x2’]))
      3. 6.1.3. 通过字典/Series进行分组(groupby(字典名))
      4. 6.1.4. 通过函数进行分组(groupby(函数))
      5. 6.1.5. 通过索引级别分组(level关键字)
    2. 6.2. 数据聚合
      1. 6.2.1. 无索引的形式返回聚合数据(as_index=False禁用)
    3. 6.3. 分组级运算和转换
      1. 6.3.1. transform和apply
      2. 6.3.2. 禁止分组键(group_keys=False)
      3. 6.3.3. 分位数(quantile)和桶(bucket)分析
      4. 6.3.4. (示例)用特定于分组的值填充缺失值(fillna方法)
      5. 6.3.5. (示例)随机采样和排列(random.permutation方法)
    4. 6.4. 透视表(pivot table)和交叉表(crosstab)
  7. 7. 时间序列(time series)
    1. 7.1. 日期和时间数据类型及工具(datetime模块)
    2. 7.2. 字符串和datetime之间的转换(strptime/strftime方法)
    3. 7.3. 时间序列基础
      1. 7.3.1. 索引、选取、子集构造(和Series一致)
    4. 7.4. 日期的范围/频率/移动
      1. 7.4.1. 生成日期范围(pandas.data_range)
      2. 7.4.2. 频率和日期偏移量(freq属性)
      3. 7.4.3. 移动(超前和滞后)数据(shift方法)
        1. 7.4.3.1. 通过偏移量对日期进行位移(rollback和rollforward方法)
    5. 7.5. 时区处理(第三方库pytz)
    6. 7.6. 本地化(tz_localize)和转换(tz_convert)
    7. 7.7. 时期+算数运算(pd.Period类)
      1. 7.7.1. 时期的频率转换(asfreq方法)
      2. 7.7.2. 通过数组创建PeriodIndex
    8. 7.8. 重采样(resampling)+频率转换
      1. 7.8.1. 重采样(resample方法)
      2. 7.8.2. 降采样(resample方法更改属性)
      3. 7.8.3. OHLC降采样(属性how=’ohlc’)
      4. 7.8.4. groupby降采样(groupby加上lambda字符串)
      5. 7.8.5. 升采样和插值(fill_method属性和limit属性)
      6. 7.8.6. 通过时期进行重采样
    9. 7.9. 移动窗口函数
,