pandas操作

一.pandas索引

1.Series索引index

2.DateFrame行索引index和列索引columns

3.pandas预置索引的类

4.重复索引

4.1重复索引定义

4.2重复索引处理groupby()

5.多级索引pd.MultiIndex

5.1Series多级索引

5.1.1.新建多级索引

5.2.2.选取元素

5.2 DataFrame多级索引

5.2.1新建DataFrame

5.2.2选取元素

5.2.3索引交换

5.2.4索引排序

5.2.5统计索引

5.2.6索引 index和列columns的转换

二.分组计算

1.原理

2.对 Series 进行分组

3.对Dataframe进行分组

3.1按行分组

3.1.1分组groupby

3.1.2groupby()支持迭代

3.2按列分组

3.2通过字典进行分组

3.3通过函数分组

3.3多级索引数据根据索引级别来分组

三.聚合统计

1.数据聚合

1.1内置聚合函数

1.2自定义聚合函数agg()

1.3应用多个聚合函数

1.4给不同的列应用不同的聚合函数

1.4重置索引

2.分组运算和转换

2.1分组数据变换transform

2.2apply函数

2.3apply 应用示例:用不同的分组平均值填充空缺数据

四.数据导入与导出/数据IO

1.索引及列名

1.1规则分隔符情况

1.2不规则分隔符情况-正则表达式

2.缺失值处理

3.逐块处理数据

4.保存数据到磁盘df.to_csv

5.二进制数据

五.时间序列

1.Python datetime模块

1.1 时间datetime

1.2时间差timedelta

1.3字符串和 datetime 转换

2.Pandas 里的时间序列

3.日期范围pd.date_range

3.1生成日期范围

3.2生成的时间频率设定,默认是D天

4.时间及其算术运算

4.1生成

4.2时期序列pd.period_range

4.3时期的频率转换

4.3.1asfreq

4.3.2季度时间频率

4.3.3 Timestamp 和 Period 相互转换

4.时间重采样

4.1降采样

4.2OHLC 重采样

4.3groupby()重采样

4.4升采样和插值

4.5时期重采样

4.6 从文件中解析时间序列

4.7自定义时间日期解析函数

六.数据可视化

1.线型图

1.1Series线型图

1.2DataFrame线型图

2.柱状图

3.频率直方图

4.概率密度图

5.带密度估计的规格化直方图

6.散布图

7.饼图

8.高级绘图

8.1举例说明scatter_matrix,散点图矩阵图

8.2lag_plot

8.3autocorrelation_plot

七.实例:股票数据分析

1.股票数据获取

2.股票波动幅度分析

八.实例:时间事件日志

九.课程小结

1.课程回顾

2.课程展望

一.pandas索引

1.Series索引index

更改索引名

2.DateFrame行索引index和列索引columns

更改行索引index和列索引columns的名

3.pandas预置索引的类

查询pandas预置索引的类

4.重复索引

4.1重复索引定义

索引值有重复的项

判断是否有重复索引

s = pd.Series(np.arange(6),index=list('abcbda'))

s['a']

s['c']

# s的索引是否是唯一值

s.index,is_unique

# s的唯一值索引

s.index.unique()

4.2重复索引处理groupby()

对重复索引的数据有一些处理,比如要对重复索引数据进行清洗,清洗方法跟业务需求关联,有时候只需要对重复的索引保留第一个,有时候要将重复索引的两个值相加起来,有时候要将重复索引的值求平均值。

# 用groupby()先将数据分组,再用函数处理

s.groupby(s.index).sum() #用s.index分组,再对分组的值求和

5.多级索引pd.MultiIndex

多级索引可以将更高维度的数据用二维数据来表示

比如股票数据,一级行索引用日期,二级行索引用不同股票代码,列索引是开盘价,收盘价,成交量数据。这样就把一个三维数据用二维来表达。可以将不同的几个股票放到同一个时间维度里面来考察。

5.1Series多级索引

5.1.1.新建多级索引

# 用列表生成多级索引

# 生成两个分别包含6个元素的对应列表,将两个对应列表解包,生成6对元组。

a = [['a','a','a','b','b','c','c'],[1,2,3,1,2,2,3]]

# zip函数将这两个列表组装起来。两两组合,生成6个元组。

t = list(zip(*a))

t

# 列表包含元组,用来创建多级索引。

# 后面是给索引赋予名字,第一级索引是level,第二级索引是level2

index = pd.MultiIndex.from_tuples(t,names=['level1','level2'])

index

# 创建出来MultiIndex对象

# 用这个对象来创建DataFrame或Series

s = pd.Series(np.random.randn(7),index=index)

5.2.2.选取元素

# 用第一级索引选取

s['b'] #选出level2为索引的Series

s['b':'c']

s[['a','c']]

# 用第二级索引选取

s[:2]

5.2 DataFrame多级索引

5.2.1新建DataFrame

df = pd.DataFrame(np.random.randint(1,10,(4,3)),

index=[['a','a','b','b'],[1,2,1,2]],

columns=[['one','one','two'],['blue','red','blue']])

# index是4个元素。即为四行。columns是3个元素,即为3列。np.random.randint(1,10,(4,3)即为生成4*3的array。

df.index.names = ['row-1','row-2']

df.columns.names = ['col-1','col-2']

df

5.2.2选取元素

df.loc['a'] #选取第一级索引

type(df.loc['a'])

df.loc['a',1] #选取第二级索引

type(df.loc['a',1])

df.loc['a',1].index

5.2.3索引交换

df2 = df.swaplevel('row-1', 'row-2') #swap,交换调换交易代替

df2

5.2.4索引排序

df2.sort_index(0) #默认按照行索引排序。0表示第一层

df2.sort_index(1) #1表示第二层

5.2.5统计索引

df

df.sum(level=0) #计算第一层

df.sum(level=1) #计算第二层

5.2.6索引 index和列columns的转换

通常情况下,从外面的data文件中读取出来的dataframe,都是单行,多列的,不便于统计。

df = pd.DataFrame({

'a': range(7),

'b': range(7, 0, -1),

'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],

'd': [0, 1, 2, 0, 1, 2, 3]

})

df

df.set_index('c')

# 转换为多级索引

df2 = df.set_index(['c', 'd'])

df2

# 重新将多级索引转换为平面的一级索引

df3 = df2.reset_index()

# 发现df3和原来的df相比,列的顺序发生变化,要将列重新排序

df3 = df2.reset_index().sort_index('columns')

df3

(df3 == df)

二.分组计算

1.原理

2.对 Series 进行分组

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a'],

'key2': ['one', 'two', 'one', 'two', 'one'],

'data1': np.random.randint(1, 10, 5),

'data2': np.random.randint(1, 10, 5)})

df

# 对 Series 进行分组,通过索引对齐关联起来

grouped = df['data1'].groupby(df['key1'])

grouped.mean()

df['data1'].groupby([df['key1'], df['key2']]).mean()

3.对Dataframe进行分组

3.1按行分组

3.1.1分组groupby

df.groupby('key1').mean()

means = df.groupby(['key1', 'key2']).mean()['data1'] #指定两个分组依据,生成多层索引的分组结果

means

means.unstack() #unstack取消堆叠。unstack()转换为dataframe,有行索引和列索引

df.groupby(['key1', 'key2'])['data1'].mean()

3.1.2groupby()支持迭代

for name,group in df.groupby('key1'):

print (name)

print (group)

# 根据key1分组可分为两个分组,a和b。可以直接迭代groupby().

# 由于groupby()支持迭代器协议,可以将其转换为列表/字典

dict(list(df.groupby('key1')))

# 这个字典的元素

dict(list(df.groupby('key1')))['a']

3.2按列分组

# 查看每列的数据类型

df.dtypes

# 按列分组,按照数据类型不同分组,object和int32

grouped = df.groupby(df.dtypes, axis=1)

#将其转化为字典

dict(list(grouped))

#分组计算

df.groupby(df.dtypes, axis=1).sum() # object进行字符串加法

3.2通过字典进行分组

df = pd.DataFrame(np.random.randint(1, 10, (5, 5)),

columns=['a', 'b', 'c', 'd', 'e'],

index=['Alice', 'Bob', 'Candy', 'Dark', 'Emily'])

df

# 赋值为非数字,观察对非数字的处理

df.iloc[1, 1:3] = np.NaN

df

# 新建映射字典

mapping = {'a': 'red', 'b': 'red', 'c': 'blue', 'd': 'orange', 'e': 'blue'}

# 新建字典,用字典映射分组

grouped = df.groupby(mapping, axis=1) #映射是根据列作的,所以用列分组

# 分组计算

grouped.sum()

grouped.count()

grouped.size()

3.3通过函数分组

当函数作为分组依据时,数据表里的每个索引(可以是行索引,也可以是列索引)都会调用一次函数,函数的返回值作为分组的索引,即相同的返回值分在同一组。

df = pd.DataFrame(np.random.randint(1, 10, (5, 5)),

columns=['a', 'b', 'c', 'd', 'e'],

index=['Alice', 'Bob', 'Candy', 'Dark', 'Emily'])

df

# 定义函数

def _dummy_group(idx): #函数的参数就是分组时要计算的分组的名字

print(idx) #打出索引名

return idx #返回索引名字

df.groupby(_dummy_group)

df.groupby(_dummy_group).size()

grouped = df.groupby(_dummy_group)

grouped.sum()

grouped.size()

grouped.count()

# 重新定义函数

def _dummy_group(idx): #

print(idx)

return len(idx)

df.groupby(_dummy_group,axis=1)

grouped = df.groupby(len)

grouped.sum()

grouped.size()

grouped.count()

# 可以直接按照长度len()来分组

df.groupby(len).size()

3.3多级索引数据根据索引级别来分组

columns = pd.MultiIndex.from_arrays([['China', 'USA', 'China', 'USA', 'China'],

['A', 'A', 'B', 'C', 'B']], names=['country', 'index'])

df = pd.DataFrame(np.random.randint(1, 10, (5, 5)), columns=columns)

df

# columns的countyy索引分组

df.groupby(level='country', axis=1).count() #必须指定axis=1按列分组,否则默认按行分组。但是行中无country参数

df.groupby(level='country', axis=1).sum()

# columns的index索引分组

df.groupby(level='index', axis=1).count()

三.聚合统计

分组运算,先根据一定规则拆分后的数据,然后对数据进行聚合运算,如前面见到的 mean(), sum() 等就是聚合的例子。聚合时,拆分后的第一个索引指定的数据都会依次传给聚合函数进行运算。最后再把运算结果合并起来,生成最终结果。

聚合函数除了内置的 sum(), min(), max(), mean() 等等之外,还可以自定义聚合函数。自定义聚合函数时,使用 agg() 或 aggregate() 函数。

1.数据聚合

1.1内置聚合函数

# 用字典生成DataFrame

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a'],

'key2': ['one', 'two', 'one', 'two', 'one'],

'data1': np.random.randint(1, 10, 5),

'data2': np.random.randint(1, 10, 5)})

df

df['data1'].groupby(df['key1']).sum()

# pandas内置聚合函数

sum(),mean(),min(),max(),describe()

1.2自定义聚合函数agg()

# 自定义函数。聚合函数中的参数就是逐个索引所对应的记录

def peak_verbose(s):

print type(s)

return s.max() - s.min()

def peak(s):

return s.max() - s.min()

# 分组

grouped = df.groupby('key1')

# 应用自定义函数

grouped.agg(peak_verbose)

1.3应用多个聚合函数

# 多个聚合函数一起计算。内置函数用字符串,自定义函数就用函数名

grouped['data1', 'data2'].agg(['mean', 'std', peak])

# 给聚合后的列取名,传元组

grouped['data1'].agg([('agerage', 'mean'), ('max-range', peak)])

1.4给不同的列应用不同的聚合函数

使用 dict 作为参数来实现

d = {'data1': ['mean', peak, 'max', 'min'],

'data2': 'sum'}

grouped.agg(d)

1.4重置索引

将key1作为dataframe中的一个column列,而不是index行索引。reset_index()

grouped.agg(d).reset_index()

# 在作聚合运算时就设置好参数,as_index=False,就不会默认把分组时的key1作为index行索引。

df.groupby('key1', as_index=False).agg(d)

2.分组运算和转换

新建dataframe

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a'],

'key2': ['one', 'two', 'one', 'two', 'one'],

'data1': np.random.randint(1, 10, 5),

'data2': np.random.randint(1, 10, 5)})

df

2.1分组数据变换transform

k1_mean = df.groupby('key1').mean()

k1_mean

k1_mean = df.groupby('key1').mean().add_prefix('mean_') #prefix,前缀,加前缀

k1_mean

# merge()函数将两个表合并起来。left_on是进行y连接,

pd.merge(df, k1_mean, left_on='key1', right_index=True)

使用 transform 简化处理

# transform()函数将数据转换为和元数据一样的dataframe,再将列名重命名

k1_mean = df.groupby('key1').transform(np.mean).add_prefix('mean_')

k1_mean

# 直接往df中新添加两个列,不用merge()函数

df[k1_mean.columns] = k1_mean

df

举例说明transform()函数

df = pd.DataFrame(np.random.randint(1, 10, (5, 5)),

columns=['a', 'b', 'c', 'd', 'e'],

index=['Alice', 'Bob', 'Candy', 'Dark', 'Emily'])

df

# 距平化

def demean(s):

return s - s.mean()

key = ['one', 'one', 'two', 'one', 'two']

demeaned = df.groupby(key).transform(demean)

demeaned

df.groupby(key).mean()

demeaned.groupby(key).mean()

2.2apply函数

我们介绍过 DataFrame 的 apply 函数是逐行或逐列来处理数据。GroupBy 的 apply 函数对每个分组进行计算。

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a', 'a', 'a', 'b', 'b', 'a'],

'key2': ['one', 'two', 'one', 'two', 'one', 'one', 'two', 'one', 'two', 'one'],

'data1': np.random.randint(1, 10, 10),

'data2': np.random.randint(1, 10, 10)})

df

# 根据 column 排序,输出其最大的 n 行数据。排序是从1开始。索引是从0开始。

def top(df, n=2, column='data1'): #参数,给定了默认值

return df.sort_values(by=column, ascending=False)[:n]

#对比下面函数

#def top(df, n=2, column='data1'):

# return df.sort_values(by=column, ascending=False) #此处没有定义显示几行

#top(df, n=5)

# 调用top()函数

top(df, n=5)

# 要先分组,再计算。不能再用top()函数调用。

# 使用apply()调用top函数

df.groupby('key1').apply(top)

# 用apply()调用top函数,且传递top()函数中的参数

df.groupby('key1').apply(top, n=3, column='data2')

# 分组后计算,top(),每一组输出规定的几行,因而最后输出n*2行

# 禁用分组键,即不出现分组键

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

2.3apply 应用示例:用不同的分组平均值填充空缺数据

states = ['Ohio', 'New York', 'Vermont', 'Florida',

'Oregon', 'Nevada', 'California', 'Idaho']

group_key = ['East'] * 4 + ['West'] * 4

data = pd.Series(np.random.randn(8), index=states)

data[['Vermont', 'Nevada', 'Idaho']] = np.nan

data

# 填充Series中的空值。东部州用东部平均值填充,西部州用西部平均值填充。

data.groupby(group_key).mean()

fill_mean = lambda g: g.fillna(g.mean())

data.groupby(group_key).apply(fill_mean)

#或者

data.groupby(group_key).apply(lambda g: g.fillna(g.mean()))

四.数据导入与导出/数据IO

数据IO:即可从磁盘中读入数据,也可以将数据保存到磁盘上。

实际工程中的操作步骤:通过爬虫爬取一些数据,对爬取的数据进行解析和清洗,之后将数据保存为csv格式文件,这个文件可能很大,pandas就从这个文件中读取数据出来,进行分析。

pandas在读入数据时会作一些操作,

第一,将一个或多个列读出来,构成一个DataFrame,其中包括索引和列名。列名可以从文件中读取,也可以指定。

第二,类型推断和数据转换:包括用户自定义的转换以及缺失值标记。比如说,遇到数字会自动将之转换成int或float,字符串就是str。

第三,日期解析。 数据中包含一些日期,可以将其解析为python中timerange数据类型,且pandas中有其自己定义的数据类型。

第四,迭代:针对大文件进行逐块迭代。这个是Pandas和Python原生的csv库的最大区别。 数据很大,不可能将所有数据都读出来,用迭代,即文件一次读一部分,结合python的迭代或python的生成器算法对python大文件进行处理。

第五,不规整数据问题:跳过一些行,或注释等等。

1.索引及列名

1.1规则分隔符情况

import pandas as pd

import numpy as np

%more ex1.csv #magic命令查看内容

df = pd.read_csv('ex1.csv')

df

df = pd.read_csv('data/ex1.csv', sep=',')

df

#列名缺失

pd.read_csv('data/ex2.csv') #直接读,会把第一行数据当作列名称

pd.read_csv('data/ex2.csv', header=None) # header=None,会自动分配整数作为列名称

#指定列名

pd.read_csv('data/ex2.csv', header=None, names=['a', 'b', 'c', 'd', 'msg']) #没有指定index行索引,自动分配整数作为index

# 指定行索引

pd.read_csv('data/ex2.csv', header=None, names=['a', 'b', 'c', 'd', 'msg'], index_col='msg')

#多层行索引

pd.read_csv('data/ex2.csv', header=None, names=['a', 'b', 'c', 'd', 'msg'], index_col=['msg', 'a'])

1.2不规则分隔符情况-正则表达式

直接读取,可以看到不能合理解析数据

参考python标准文档re模块,详细介绍了正则表达式

# 正则表达式

pd.read_csv('data/ex3.csv', sep='\s+') #因为原文件中字符间的空格可能是一个也可能是多个,\s表示空格,+表示1到多个。

# pd.read_csv('data/ex3.csv')

#这里,数据列标签有三个,数据有4列,pandas会默认将第一列当作index。所以这里没有分配整数作为表的index,而是将数据第一列作为index

2.缺失值处理

%more data/ex5.csv

pd.read_csv('data/ex5.csv') #自动将空缺部分处理为NaN.将NA作为NaN,而不是字符串。

#缺失值可以指定。列表中的都指定为缺失值

pd.read_csv('data/ex5.csv', na_values=['NA', 'NULL', 'foo'])

#针对每一列指定不同的缺失值。用字典形式

pd.read_csv('data/ex5.csv', na_values={'message': ['foo', 'NA'], 'something': ['two']})

3.逐块处理数据

ex6.csv数据大。

要统计最后一列,key下面的元素出现的次数,然后将出现次数最多的前十个打印出来。

一种实现方法是用pandas将整个文件都读出来,然后用value_count()函数统计出来,再去排序。但是如果数据很大,就不能一次读取出来,就要用到逐快读取数据。

#老式办法,一次性读取

s=pd.read_csv('data/ex6.csv')

s.head()

# value_counts()统计出现次数

b=s['key'].value_counts()

b.head()

#或先分组,再计算每个分组的大小,默认不排序,还需排序。

a=s.groupby('key').size().sort_values(ascending=False)

a.head()

##逐快读取数据。

#先读取前10行

pd.read_csv('data/ex6.csv', nrows=10) #nrows=10,先读10行,看下数据结构

# 指定chunksize,一次读取多少行,先读取1000行。

tr = pd.read_csv('data/ex6.csv', chunksize=1000)

# 返回结果是,TextFileReader是解析器,支持迭代。可用for循环。这个tr整体不是pndas函数可操作对象,因而必须遍历出来。

# 遍历出来tr中的值

key_count = pd.Series([])

for pieces in tr:

key_count = key_count.add(pieces['key'].value_counts(), fill_value=0)

key_count = key_count.sort_values(ascending=False) #pd.Series默认乱序,所以还需排序

key_count[:10]

chunksize,块大小,块尺寸

4.保存数据到磁盘df.to_csv

#读取数据

df = pd.read_csv('data/ex5.csv')

df

#保存数据到磁盘。默认情况下将索引值也写入文件,文件中会多出来一些额外的值。

df.to_csv('data/ex5_out.csv')

%more data/ex5_out.csv

# 验证上面新保存的数据

df = pd.read_csv('data/ex5_out.csv')

df

#保存时不写索引。默认情况下会将索引值也写入data文件,因而data文件会多出来一行/一列值

df = pd.read_csv('data/ex5.csv')

df.to_csv('data/ex5_out.csv', index=False)

%more data/ex5_out.csv

#保存时不写索引

df = pd.read_csv('data/ex5.csv')

df.to_csv('data/ex5_out.csv', index=False, header=None)

%more data/ex5_out.csv

#保存时指定分隔符

%more data/ex5_out.csv

# 保存时只写出一部分列

df = pd.read_csv('data/ex5.csv')

df.to_csv('data/ex5_out.csv', index=False, columns=['a', 'b', 'message'])

%more data/ex5_out.csv

5.二进制数据

二进制的优点是容量小,读取速度快。缺点是可能在不同版本间不兼容。比如 Pandas 版本升级后,早期版本保存的二进制数据可能无法正确地读出来。

用pickle包实现

HDF5: HDF5是个C语言实现的库,可以高效地读取磁盘上的二进制存储的科学数据

Excel文件: pd.read_excel/pd.ExcelFile/pd.ExcelWriter

JSON: 通过 json 模块转换为字典,再转换为 DataFrame

SQL 数据库:通过 pd.io.sql 模块来从数据库读取数据

NoSQL (MongoDB) 数据库:需要结合相应的数据库模块,如 pymongo 。再通过游标把数据读出来,转换为 DataFrame

这些具体可以参阅pandas官方文档

用pickle举例说明,pd.to_pickle()

#读取文件

df = pd.read_csv('data/ex1.csv')

df

#将读取出来的数据写入data/ex1_pickle.bin

pd.to_pickle(df, 'data/ex1_pickle.bin')

%ls data

#读取data/ex1_pickle.bin

pd.read_pickle('data/ex1_pickle.bin')

# 读取写入一次性操作

pd.to_pickle(pd.read_csv('data/ex6.csv'), 'data/ex6_pickle.bin')

#%ls data

五.时间序列

时间日期

stamp,邮票;印记;标志。interval,间隔;间距;幕间休息

时间戳 tiimestamp:固定的时刻 -> pd.Timestamp

固定时期 period:比如 2016年3月份,再如2015年销售额 -> pd.Period

时间间隔 interval:由起始时间和结束时间来表示,固定时期是时间间隔的一个特殊

时间日期在 Pandas 里的作用

分析金融数据,如股票交易数据

分析服务器日志

1.Python datetime模块

1.1 时间datetime

python 标准库里提供了时间日期的处理。这个是时间日期的基础

timedelta,时间间隔,日期时间间隔对象

from datetime import datetime

from datetime import timedelta

now = datetime.now()

now

now.year, now.month, now.day

1.2时间差timedelta

date1 = datetime(2016, 3, 20)

date2 = datetime(2016, 3, 16)

delta = date1 - date2

delta

delta.days

delta.total_seconds()

date2 + delta

date2 + timedelta(4.5)

1.3字符串和 datetime 转换

关于 datetime 格式定义,可以参阅 python 官方文档

date = datetime(2016, 3, 20, 8, 30)

date

str(date)

date.strftime('%Y-%m-%d %H:%M:%S') #date.strftime格式化样式,后面()中为想要给定的样式

datetime.strptime('2016-03-20 09:30', '%Y-%m-%d %H:%M') #再把时间日期格式转换为python内部格式

2.Pandas 里的时间序列

Pandas 里使用 Timestamp 来表达时间

dates = [datetime(2016, 3, 1), datetime(2016, 3, 2), datetime(2016, 3, 3), datetime(2016, 3, 4)] #时间列表

s = pd.Series(np.random.randn(4), index=dates)

s

type(s.index) #DatetimeIndex数据结构

type(s.index[0]) #Timestamp数据结构

pandas中提供了更方便的生成时间序列的方法,生成时间戳的时间序列的方法就是pd.date_range

3.日期范围pd.date_range

3.1生成日期范围

pd.date_range('20160320', '20160331') #接收开始时间到结束时间

pd.date_range(start='20160320', periods=10) #开始时间和生成个数

## 规则化时间戳

pd.date_range(start='2016-03-20 16:23:32', periods=10)

pd.date_range(start='2016-03-20 16:23:32', periods=10, normalize=True) #

3.2生成的时间频率设定,默认是D天

## 星期

pd.date_range(start='20160320', periods=10, freq='W')

# 月

pd.date_range(start='20160320', periods=10, freq='M')

## 每个月最后一个工作日组成的索引

pd.date_range(start='20160320', periods=10, freq='BM')

# 小时

pd.date_range(start='20160320', periods=10, freq='4H')

4.时间及其算术运算

pd.Period 表示时期,比如几日,月或几个月等。比如用来统计每个月的销售额,就可以用时期作为单位。

4.1生成

Period(‘2010’, ‘A-DEC’),A表示anual年的,DEC,December十二月,在十二月结束。

4.2时期序列pd.period_range

# 单位是月,即频率

pd.period_range(start='2016-01', periods=12, freq='M')

pd.period_range(start='2016-01', end='2016-10', freq='M')

# 单位是季度

pd.period_range('2016-Q1',periods=10,freq='Q')

# 直接用字符串

index = pd.PeriodIndex(['2016Q1', '2016Q2', '2016Q3'], freq='Q-DEC')

index

freq='Q-DEC’表示Q季度是以DEC12月结束的单位

4.3时期的频率转换

4.3.1asfreq

sfreq

A-DEC: 以 12 月份作为结束的年时期

A-NOV: 以 11 月份作为结束的年时期

Q-DEC: 以 12 月份作为结束的季度时期

# 生成2016年时间段,单位是anual,以December结尾

p = pd.Period('2016', freq='A-DEC')

p

# 转换为月,默认以年的终点作为新的时期

p.asfreq('M')

# 设定以年的开始作为新的时期

p.asfreq('M', how='start')

# 生成新的月

p = pd.Period('2016-04', freq='M')

p

#将月转换为年,设定频率为A-DEC

p.asfreq('A-DEC')

# 以年为周期,以一年中的3月份作为年的结束(财年),设定为A-MAR

p.asfreq('A-MAR') #那么4月份就是下一年

4.3.2季度时间频率

Pandas 支持 12 种季度型频率,从 Q-JAN 到 Q-DEC区别是以哪个月作为一年的结束

# 生成2016年第4季度,以1月份结束

p = pd.Period('2016Q4', 'Q-JAN')

p

# 以 1 月份结束的财年中,2016Q4 的时期是指 2015-11-1 到 2016-1-31

p.asfreq('D', how='start'), p.asfreq('D', how='end')

##获取该季度倒数第二个工作日下午4点的时间戳

# 先将原来的时间转换为工作日B,先得出最后一天how='end',倒数第二个工作日,那就再减去1。下午4点,就再转换为分钟T,先得出最开始'start',再加上16 * 60,就得到16点。

p4pm = (p.asfreq('B', how='end') - 1).asfreq('T', 'start') + 16 * 60

p4pm

# 转换为 timestamp

p4pm.to_timestamp()

4.3.3 Timestamp 和 Period 相互转换

这是重采样的一种

# Timestamp时间戳序列,freq='M'

ts = pd.Series(np.random.randn(5), index = pd.date_range('2016-01-01', periods=5, freq='M'))

ts

# 转换为Period时间段时间序列,freq='M',但是时间变为时间段

ts.to_period()

#Timestamp序列,freq='D'

ts = pd.Series(np.random.randn(5), index = pd.date_range('2016-12-29', periods=5, freq='D'))

ts

#转换为Period时间段时间序列,freq='D',但是时间变为时间段

pts = ts.to_period() #默认直接转换为日时间段

pts

#转换为月时间段时间序列

pts = ts.to_period(freq='M') #月是重复的,把重复的月合并掉就要按月分组

pts

#按月分组

pts.groupby(level=0).sum()

# 转换为时间戳,由月转换回来,会丢失掉具体时间,而只剩下每个月的一天

pts.to_timestamp() #默认转换为每个月的第一天

pts.to_timestamp(how='end') #设定转换为每个月的最后一天

4.时间重采样

高频率 -> 低频率 -> 降采样:5 分钟股票交易数据转换为日交易数据

低频率 -> 高频率 -> 升采样

其他重采样:每周三 (W-WED) 转换为每周五 (W-FRI)

4.1降采样

# 新建一个Series

ts = pd.Series(np.random.randint(0, 50, 60), index=pd.date_range('2016-04-25 09:30', periods=60, freq='T'))

ts

# 按5分钟为一组降采样。计算方法为sum(),默认以起始时间作为行索引。

ts.resample('5min').sum()

# label='right'。设定以结束时间作为行索引

ts.resample('5min',label='right').sum()

4.2OHLC 重采样

金融数据专用:Open/High/Low/Close

ts.resample('5min').ohlc()

4.3groupby()重采样

# 新建时间序列

ts = pd.Series(np.random.randint(0, 50, 100), index=pd.date_range('2016-03-01', periods=100, freq='D'))

ts.head()

通过月份进行重采样

# 方法1:新建一个lambda函数

ts.groupby(lambda x: x.month).sum() #x就是Series的逐个索引,即日期。x.month,是日期的月份

# 方法2:将时间戳序列转为时期序列ts.index.to_period('M'),时期是以月份为单位

ts.groupby(ts.index.to_period('M')).sum()

4.4升采样和插值

# 以周为单位,每周五采样

df = pd.DataFrame(np.random.randint(1, 50, 2), index=pd.date_range('2016-04-22', periods=2, freq='W-FRI'))

#freq='W-FRI',是以周为单位,且以周五为每周的结束

df

# 要将以周为单位的数据转化为以天为单位,这时就要用到插值。22好到29号2之间原本没有值,现在要转换为以天为单位,就要插值。

df.resample('D')

df.resample('D').ffill()

df.resample('D').ffill(limit=3)

# 将每周五为一周结束的采样周期转换为每周一为一周结束的采样周期

df.resample('W-MON').ffill()

4.5时期重采样

# 新建DataFrame,单位为月

df = pd.DataFrame(np.random.randint(2, 30, (24, 4)),

index=pd.period_range('2015-01', '2016-12', freq='M'),

columns=list('ABCD'))

df.head(10)

# 重采样为单位为年,以Decemeber为一年的结束

adf = df.resample('A-DEC').mean()

adf

# 重采样为单位为年,以May为一年的结束

df.resample('A-MAY').mean()

##升采样

# 重采样为季度为单位,以December结束

adf.resample('Q-DEC')

adf.resample('Q-DEC').ffill()

4.6 从文件中解析时间序列

将上面的文件读取出来,解析为datetime时间序列。

df = pd.read_csv('data/002001.csv')#直接读取,自动给定index为整数

df = pd.read_csv('data/002001.csv', index_col='Date') #设定index为Date

df #结果看着是时间日期,实际上不是,因为不会默认解析为时间日期

df.index # dtype='object', name='Date',不是datetime

df = pd.read_csv('data/002001.csv', index_col='Date', parse_dates=True) #parse_dates=True,解析日期

df.index #dtype='datetime64[ns]', name='Date', freq=None

# 解析出来时间日期有什么好处?要把日交易数据根据赋权后的收盘价转换为周数据

wdf = df['Adj Close'].resample('W-FRI').ohlc()

wdf

# 新添加一列Volume

wdf['Volume'] = df['Volume'].resample('W-FRI').sum()

wdf

parse,解析,理解

4.7自定义时间日期解析函数

def date_parser(s):

s = '2016/' + s

d = datetime.strptime(s, '%Y/%m/%d')

return d

# 这个函数是用来将字符串格式的时间'%Y/%m/%d'转换为dtype='datetime64时间格式

df = pd.read_csv('data/custom_date.csv', parse_dates=True, index_col='Date', date_parser=date_parser)

df

df.index

#datetime.strptime(s, '%Y/%m/%d')函数,将字符串格式的时间'%Y/%m/%d'转换为dtype='datetime64'时间格式

datetime.strptime()函数,详见https://blog.csdn.net/lengyuezuixue/article/details/87950493

六.数据可视化

Pandas 的数据可视化使用 matplotlib 为基础组件,是python的专门用来实现数据可视化的一个库。更基础的信息可参阅 matplotlib 相关内容。

本节主要介绍 Pandas 里提供的比利用matplotlib 来封装的更便捷的数据可视化操作。

更多内容可参照网上搜索资料或者官方文档

%matplotlib inline #要把图片直接画到网页中,启用matplotlib inline模式

import pandas as pd

import numpy as np

1.线型图

1.1Series线型图

Series 和 DataFrame 都提供了一个 plot 的函数。可以直接画出线形图。

ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))

ts = ts.cumsum() #累加

ts.describe()

ts.plot()

#这个输出不想看到,可以在后面加上分号,就不会出现了

ts.plot(title='cumsum', style='r-', ylim=[-30, 30], figsize=(4, 3))

#style='r-',设置线型图形状,r是red,虚线是--。figs=(4, 3)是图片大小。

1.2DataFrame线型图

df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list('ABCD'))

df = df.cumsum() # 默认对每一列累计求和

df.describe() #数据描述

df.plot() #四列四条线画在一起,自动给定一个图例。如果是在matplotlib中,这些x/y轴标签,图例都要自己去画。pandas中更方便。默认将idex作为x轴,也可以指定index

# 二维数组DataFrame画图有自己的特有参数,subplots=True,把每个列单独画在一个子图中;sharex=True,x轴共用,即4个图x轴一样;sharey=True,y轴共用,即4个图,y轴一样。默认将idex作为x轴,也可以指定index

df.plot(title='DataFrame cumsum', figsize=(4, 12), subplots=True, sharex=True, sharey=True);

#指定index

#在原df中新增一个列I

df['I'] = np.arange(len(df))

df.plot(x='I', y=['A', 'C']) #指定x轴和y轴

2.柱状图

df = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])

df

# 指定一行,画图

df.iloc[1].plot(kind='bar')

df.iloc[1].plot.bar()

# 不指定,默认画出所有行的所有列。每个点都是四列。按行定点,每行区分为4列。

df.plot.bar()

# 上面的柱子是独立画的,也可以堆叠起来。stacked=True

df.plot.bar(stacked=True)

#bar后面加上h,表示横向柱状图Horizontal

df.plot.barh(stacked=True)

stack,一堆,堆叠;Horizontal,横向的

3.频率直方图

直方图是一种对值频率进行离散化的柱状图。数据点被分到离散的,间隔均匀的区间中,绘制各个区间中数据点的数据。

df = pd.DataFrame({'a': np.random.randn(1000) + 1, 'b': np.random.randn(1000),

'c': np.random.randn(1000) - 1}, columns=['a', 'b', 'c'])

df.head()

# 选择a列画直方图,

df['a'].plot.hist(bins=20)

# 直方图的意思就是将所有值按照从小到大排列起来,按照值,将值以最小和最大为界,分成20等分的大小区间,这些点对应的值落在每个区间中点的个数。x轴是20等分的值大小,y轴是区间中点的个数。比如说,落在值大小1到2区间中点的个数。

#random默认是正态分布,所以图中就是一个类似正态分布的图。中间点数最多,两边点数最少。

df['a'].plot.hist(bins=20) #去掉格网,加上中间的.plot

df.plot.hist(subplots=True, sharex=True, sharey=True)

#画出所有列的直方图

df.plot.hist()

# 三个直方图画在一起被遮挡住,可以调整透明值

df.plot.hist(alpha=0.5) #alpha,透明度

#还是不好看,可以加上stacked,叠加,不需再透明

df.plot.hist(stacked=True)

df.plot.hist(stacked=True, bins=20, grid=True)

# 将每个直方图分开画,subplots=True, sharex=True, sharey=True,且共享x和y轴

df.plot.hist(subplots=True, sharex=True, sharey=True)

hist,频数计算或频数直方图,直方图,统计频数直方图

alpha,透明度,

4.概率密度图

表示一个事件发生的可能性,用来衡量一个事件发生的概率大小。

# 新建DataFrame

df = pd.DataFrame({'a': np.random.randn(1000) + 1, 'b': np.random.randn(1000),

'c': np.random.randn(1000) - 1}, columns=['a', 'b', 'c'])

df.head()

# plot.kde()绘制概率密度图

df['a'].plot.kde() #结果符合正态分布

df.plot.kde() #三列都画出来,三个概率密度图

# 决定正太密度图倒装形的有两个因素,均值和方差。均值决定概率密度图中心点的位置,概率密度图是窄的还是宽的由方差决定。三列的方差都差不多所以形状类似。

df.mean() #三列均值

df.std() #三列的std

5.带密度估计的规格化直方图

# 生成Y轴为对称轴,scale=1,包含200个数字的正态分布一维array

n1 = np.random.normal(0, 1, size=200)

# N(0, 1)。np.random.normal()的意思是一个正态分布,normal这里是正态的意思

# 生成Y=10为对称轴,scale=2,包含200个数字的正态分布的一维array

n2 = np.random.normal(10, 2, size=200) # N(10, 4)

# np.concatenate([n1, n2]),将两个array组合起来,有两组200个数字组合为一组400个数字,原来的array没变。生成Series

s = pd.Series(np.concatenate([n1, n2]))

# S,包含两组正态分布数字的Series

s.describe()

np.random.normal()的意思是一个正态分布,normal这里是正态的意思。

numpy.random.normal(loc=0,scale=1e-2,size=shape) ,意义如下:

参数loc(float):正态分布的均值,对应着这个分布的中心。loc=0说明这一个以Y轴为对称轴的正态分布,

参数scale(float):正态分布的标准差,对应分布的宽度,scale越大,正态分布的曲线越矮胖,scale越小,曲线越高瘦。

参数size(int 或者整数元组):输出的值赋在shape里,默认为None。

concatenate,连接,连结,使连锁

np.concatenate((a1,a2,...), axis=0)),能够一次完成多个数组的拼接。其中a1,a2,...是数组类型的参数。

s.plot.hist(bins=100, alpha=0.5, normed=True)

s.plot.kde(style='r-')

6.散布图

散布图是把所有的点画在同一个坐标轴上的图像。是观察两个一维数据之间关系的有效的手段。

举例说明一

df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])

df

df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])

df.plot.scatter(x='a', y='b');

举例说明2

df = pd.DataFrame({'a': np.concatenate([np.random.normal(0, 1, 200), np.random.normal(6, 1, 200)]),

'b': np.concatenate([np.random.normal(10, 2, 200), np.random.normal(0, 2, 200)]),

'c': np.concatenate([np.random.normal(10, 4, 200), np.random.normal(0, 4, 200)])})

df.describe()

# a、b、c之间有什么关系?通过散布图可以作直观的观察

df.plot.scatter(x='a', y='b')

# 结果,a和b的点明显分为两团,有明显的分界线,这样可以直观看到这些点数据有什么分布规律

7.饼图

s = pd.Series(3 * np.random.rand(4), index=['a', 'b', 'c', 'd'], name='series')

s

s.plot.pie() #默认饼图是椭圆形

s.plot.pie(figsize=(6,6)) #figsize=(6,6),指定饼图圆的形状

s.plot.pie(labels=['AA', 'BB', 'CC', 'DD'], colors=['r', 'g', 'b', 'c'],autopct='%.2f', fontsize=20, figsize=(6, 6))

# labels=['AA', 'BB', 'CC', 'DD'],指定标签。autopct='%.2f',指定百分比,'%.2f'保留两个小数点。fontsize=20,指定字体。

DataFrame画图

df = pd.DataFrame(3 * np.random.rand(4, 2), index=['a', 'b', 'c', 'd'], columns=['x', 'y'])

df

df.plot.pie(subplots=True, figsize=(9, 4))

8.高级绘图

高级绘图函数在 pandas.plotting 包里。

定制化的绘图需要学习matplotlib包的用法

8.1举例说明scatter_matrix,散点图矩阵图

scatter_matrix,scatter分散散点图散射。matrix, 矩阵;模型

散点图矩阵图,可以发现两两特征之间的联系

scatter_matrix(frame, alpha=0.5, c,figsize=None, ax=None, diagonal='hist', marker='.', density_kwds=None,hist_kwds=None, range_padding=0.05, **kwds)

1。frame,pandas dataframe对象

2。alpha, 图像透明度,一般取(0,1]

3。figsize,以英寸为单位的图像大小,一般以元组 (width, height) 形式设置

4。ax,可选一般为none

5。diagonal,必须且只能在{‘hist’, ‘kde’}中选择1个,’hist’表示直方图(Histogram plot),’kde’表示核密度估计(Kernel Density Estimation);该参数是scatter_matrix函数的关键参数

6。marker。Matplotlib可用的标记类型,如’.’,’,’,’o’等

7。density_kwds。(other plotting keyword arguments,可选),与kde相关的字典参数

8。hist_kwds。与hist相关的字典参数

9。range_padding。(float, 可选),图像在x轴、y轴原点附近的留白(padding),该值越大,留白距离越大,图像远离坐标原点

10。kwds。与scatter_matrix函数本身相关的字典参数

11。c。颜色

from pandas.plotting import scatter_matrix

df = pd.DataFrame(np.random.randn(1000, 4), columns=['a', 'b', 'c', 'd'])

scatter_matrix(df, alpha=0.2, figsize=(6, 6), diagonal='kde');

8.2lag_plot

from pandas.plotting import lag_plot

s = pd.Series(0.1 * np.random.rand(1000) + 0.9 * np.sin(np.linspace(-99 * np.pi, 99 * np.pi, num=1000)))

lag_plot(s);

8.3autocorrelation_plot

from pandas.plotting import autocorrelation_plot

s = pd.Series(0.7 * np.random.rand(1000) + 0.3 * np.sin(np.linspace(-9 * np.pi, 9 * np.pi, num=1000)))

autocorrelation_plot(s);

七.实例:股票数据分析

这部分以后再写

https://github.com/kamidox/stock-analysis

stock,股份,股票;库存

1.股票数据获取

爬虫,如何写一个爬虫来获取股票数据

python中画出距平垂线_3.机器学习—数据科学包3.3pandas操作相关推荐

  1. 机器学习---数据科学包-第2天

    1 pandas快速入门(一) .Series()方法.Series类型由一组数据及与之相关的数据索引组成. import pandas as pd import numpy as np s = pd ...

  2. 3.机器学习—数据科学包3.2pandas基础

    pandas基础 一.pandas介绍 1.什么是pandas 2.pandas用途 3.课程内容 二.Ipython开发环境搭建 1.安装 2.新建运行环境 3.Ipython技巧 4.Ipytho ...

  3. python怎么画出好看的统计图_python数据可视化之如何用matplotlib画出漂亮美观的趋势图...

    这几天完成了一个小项目,matplotlib画出的图像总是不理想,很多细节需要调节,譬如横坐标的控制.图例的控制.周边留白的控制还有图片大小尺寸的控制,都需要根据业务需求来调整. 下面我一步步来说明 ...

  4. 机器学习数据科学包(二)——Pandas入门

    目录 二.查看数据 三.选择 四.缺失值处理 五.相关操作 六.合并 七.分组 八.重塑(Reshaping) 九.时间序列 十.Categorical 十一.画图 十二.导入和保存数据 本文对十分钟 ...

  5. 机器学习---数据科学包-第4天

    1 Numpy简介 1 # 1 通过python的基础数据对象转化 2 import numpy as np 3 x = [1, 2, 3, 4] 4 x = np.array(x) 5 x Out[ ...

  6. 机器学习数据科学包(三)——Pandas实例:MovieLens电影数据分析

    电影数据分析 准备工作 从网站 grouplens.org/datasets/movielens 下载 MovieLens 1M Dataset 数据. 数据说明 参阅数据介绍文件 README.tx ...

  7. R语言可视化包ggplot2在一张图中画出两条线实战

    R语言可视化包ggplot2在一张图中画出两条线实战 目录 R语言可视化包ggplot2在一张图中画出两条线实战

  8. python画三维立体图-如何在论文中画出漂亮的插图?

    ----2020.08.07增---- 看到评论区有人说"没代码没教程所以没帮助"-- 好吧,我寻思链接.参考资料都在回答中给出来了呀(可能不够明显?) 于是,重新整理.注释了一下 ...

  9. python画笔的尺寸_Matplotlib 常用画图命令总结:使用 Python 在论文中画出一手漂亮的数据图...

    介绍 本文不是一篇详尽的.从简到繁的 Maplotlib 画图教程,而是用各种例子快速直观地让读者上手 Matplotlib 画图中的一些常用的.基础的操作.本文不对各种数据图(折线图.柱状图等)作介 ...

最新文章

  1. Python学习之路--函数
  2. hyperworks2018安装教程
  3. boost::hana::make_pair用法的测试程序
  4. OpenCV交互式相机校准应用
  5. 经典C语言程序100例之三六
  6. dailybuild
  7. 通向架构师的道路(第十七天)IBM Websphere集群探秘-WASND
  8. 自学java去哪找工作比较好_如何自学java?什么程度可以找工作?
  9. “3D几何与视觉技术”全球在线研讨会(9月2日到12月16日)
  10. mysql 不省略0_mysql数据类型和运算符
  11. RQNOJ PID2 / 开心的金明
  12. laravel5.5 后台
  13. R语言数据分析案例(1)
  14. 电脑设备打印机驱动安装失败如何解决
  15. 计算机里的游戏怎么输入,如何输入对号(对号怎么打?电脑上和手机分别怎么打?)...
  16. typora导出pdf文件缺失
  17. python爬取LOL皮肤
  18. 如何提升公众号关注率,让用户看完文章关注你
  19. Chatbot项目的剖析
  20. 转载:使用飞信VMDotNet使C#程序脱离.NET FRAMEWORK也能运行的一些心得

热门文章

  1. .NET客户端实现Redis中的管道(PipeLine)与事物(Transactions)(八)
  2. 苹果免越狱群控 手机投屏 电脑端操控手机
  3. 无法打开chromedriver的原因
  4. 魅蓝note3 android操作系统,魅族魅蓝Note3什么配置参数
  5. curl第六课 Http Digest Auth认证应用
  6. springboot毕设项目乐器定制平台7h503(java+VUE+Mybatis+Maven+Mysql)
  7. 子平真诠释疑笔记(七)
  8. 提取txt文档中以冒号分隔符区分的信息到excel(前提是使用正则表达式把每一行修改为只有一个冒号)
  9. 百度地图大数据可视化(柱状图)
  10. Flutter开发记录part2