时间日期在 Pandas 里的作用
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)
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 里使用 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函数
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')
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
# 时间戳的时间序列
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'
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')
金融数据专用:Open/High/Low/Close
ts.resample('5min', how='ohlc')
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))