pandas——时间日期及数据可视化

时间日期

  • 时间戳 tiimestamp:固定的时刻 -> pd.Timestamp
  • 固定时期 period:比如 2016年3月份,再如2015年销售额 -> pd.Period
  • 时间间隔 interval:由起始时间和结束时间来表示,固定时期是时间间隔的一个特殊

时间日期在 Pandas 里的作用

  • 分析金融数据,如股票交易数据
  • 分析服务器日志

复习Python的datetime模块

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

from datetime import datetime
from datetime import timedelta
now = datetime.now()
now.year, now.month, now.day

时间差

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)

字符串和 datetime 转换

date = datetime(2016, 3, 20, 8, 30)
str(date) # 将日期转换成字符串形式
# 日期格式化,Y代表用4位数的年份,y代表两位数的年份
date.strftime('%Y-%m-%d %H:%M:%S') 
# 指定格式,将字符串形式转换成datetime形式
datetime.strptime('2016-03-20 09:30', '%Y-%m-%d %H:%M')

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)

日期范围

生成日期范围

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

规则化时间戳

# normalize = True时后面的16:23:32会省略
pd.date_range(start='2016-03-20 16:23:32', periods=10, normalize=True)

时间频率

星期

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')

时期及算术运算

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

p1 = pd.Period(2010)
p2 = p1 + 2
p2 - p1
p1 = pd.Period(2016, freq='M')
p1 + 3
# 时期序列
pd.period_range(start='2016-01', periods=12, freq='M')
pd.period_range(start='2016-01', end='2016-10', freq='M')

直接用字符串

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

时期的频率转换

asfreq函数

  • A-DEC: 以 12 月份作为结束的年时期
  • A-NOV: 以 11 月份作为结束的年时期
  • Q-DEC: 以 12 月份作为结束的季度时期
p = pd.Period('2016', freq='A-DEC')
p.asfreq('M', how='start')
p.asfreq('M', how='end')
p = pd.Period('2016-04', freq='M')
p.asfreq('A-DEC')

以年为周期,以一年中的 3 月份作为年的结束(财年)

p.asfreq('A-MAR')

季度时间频率

Pandas 支持 12 种季度型频率,从 Q-JAN 到 Q-DEC

p = pd.Period('2016Q4', 'Q-JAN')
# 以 1 月份结束的财年中,2016Q4 的时期是指 2015-11-1 到 2016-1-31
p.asfreq('D', how='start'), p.asfreq('D', how='end')

# 获取该季度倒数第二个工作日下午4点的时间戳
p4pm = (p.asfreq('B', how='end') - 1).asfreq('T', 'start') + 16 * 60

Timestamp 和 Period 相互转换

# 时间戳的时间序列
ts = pd.Series(np.random.randn(5), index = pd.date_range('2016-01-01', periods=5, freq='M'))
ts.to_period() # 转换成了基于时期的时间序列

ts = pd.Series(np.random.randn(5), index = pd.date_range('2016-12-29', periods=5, freq='D'))
pts = ts.to_period(freq='M')
pts.groupby(level=0).sum()

# 转换为时间戳时,细部时间会丢失
pts.to_timestamp(how='end') # how默认为'start'

重采样

  • 高频率 -> 低频率 -> 降采样:5 分钟股票交易数据转换为日交易数据
  • 低频率 -> 高频率 -> 升采样
  • 其他重采样:每周三 (W-WED) 转换为每周五 (W-FRI)
ts = pd.Series(np.random.randint(0, 50, 60), index=pd.date_range('2016-04-25 09:30', periods=60, freq='T'))
# 0-4 分钟为第一组,以起始时间为行索引
ts.resample('5min', how='sum')
# 0-4 分钟为第一组,label = 'right'以结束时间为行索引
ts.resample('5min', how='sum', label='right')

OHLC 重采样

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

ts.resample('5min', how='ohlc')

通过 groupby 重采样

ts = pd.Series(np.random.randint(0, 50, 100), index=pd.date_range('2016-03-01', periods=100, freq='D'))
# 每个月为一组采样的两个实现方式
ts.groupby(lambda x: x.month).sum()
ts.groupby(ts.index.to_period('M')).sum()

升采样和插值

# 以周为单位,每周五采样
df = pd.DataFrame(np.random.randint(1, 50, 2), index=pd.date_range('2016-04-22', periods=2, freq='W-FRI'))
# 以天为单位重采样,插入的值为NaN
df.resample('D')
df.resample('D', fill_method='ffill', limit=3)
# 以周为单位,每周一采样
df.resample('W-MON', fill_method='ffill')

从文件中读取日期序列

# parse_dates=True会解析索引列,将其转换为日期格式
df = pd.read_csv('data/002001.csv', index_col='Date', parse_dates=True)

自定义时间日期解析函数

def date_parser(s):
    s = '2016/' + s
    d = datetime.strptime(s, '%Y/%m/%d')
    return d
df = pd.read_csv('data/custom_date.csv', parse_dates=True, index_col='Date', date_parser=date_parser)

数据可视化

Pandas 的数据可视化使用 matplotlib 为基础组件。更基础的信息可参阅 matplotlib 相关内容。本节主要介绍 Pandas 里提供的比 matplotlib 更便捷的数据可视化操作。
#%% md

线型图

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

ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.plot()
ts.plot(title='cumsum', style='r-', ylim=[-30, 30], figsize=(4, 3));
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list('ABCD'))
df = df.cumsum()
# subplots = True 意味着图片不合并,每列一个子图,sharex=True, sharey=True意味着各个子图的x,y坐标轴相同
df.plot(title='DataFrame cumsum', figsize=(4, 12), subplots=True, sharex=True, sharey=True);
df['I'] = np.arange(len(df))
# 自定义x,y轴
df.plot(x='I', y=['A', 'C'])

柱状图

df = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])
# 画柱状图,ix[1]选取第0行画图
df.ix[0].plot(kind='bar')
df.ix[1].plot.bar()
# stacked=True代表图堆在上方
df.plot.bar(stacked=True)
# barh代表横向画图
df.plot.barh(stacked=True)

直方图

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

df = pd.DataFrame(
		{'a': np.random.randn(1000) + 1, 
		'b': np.random.randn(1000),
        'c': np.random.randn(1000) - 1}, 
        columns=['a', 'b', 'c'])
# bins = 10分为10块
df['a'].plot.hist(bins=10)
df.plot.hist(subplots=True, sharex=True, sharey=True)
# alpha = 0.5代表设置图片透明的为0.5
df.plot.hist(alpha=0.5)
# grid = True代表显示网格
df.plot.hist(stacked=True, bins=20, grid=True)

密度图

正态分布(高斯分布)就是一种自然界中广泛存在密度图。比如我们的身高,我们的财富,我们的智商都符合高斯分布。

df['a'].plot.kde()
df.plot.kde()
df.mean()
df.std()

散布图

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

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

饼图

s = pd.Series(3 * np.random.rand(4), index=['a', 'b', 'c', 'd'], name='series')
s.plot.pie(figsize=(6,6))
# 自定义标签名和颜色字体
s.plot.pie(labels=['AA', 'BB', 'CC', 'DD'], colors=['r', 'g', 'b', 'c'],
           autopct='%.2f', fontsize=20, figsize=(6, 6))
df = pd.DataFrame(3 * np.random.rand(4, 2), index=['a', 'b', 'c', 'd'], columns=['x', 'y'])
df.plot.pie(subplots=True, figsize=(9, 4))

你可能感兴趣的:(可视化)