pandas教程:Periods and Period Arithmetic 周期和周期运算

文章目录

  • 11.5 Periods and Period Arithmetic(周期和周期运算)
  • 1 Period Frequency Conversion(周期频度转换)
  • 2 Quarterly Period Frequencies(季度周期频度)
  • 3 Converting Timestamps to Periods (and Back)(时间戳与周期相互转换)
  • 4 Creating a PeriodIndex from Arrays(从数组中创建一个周期索引)

11.5 Periods and Period Arithmetic(周期和周期运算)

Periods(周期)表示时间跨度(timespans),比如天,月,季,年。Period类表示的就是这种数据类型,构建的时候需要用字符串或整数,以及一个频度(关于频度的代码可以看11.4中的表格):

import numpy as np
import pandas as pd
p = pd.Period(2007, freq='A-DEC')
p
Period('2007', 'A-DEC')

在这个例子里,Period对象代表了整个2007年一年的时间跨度,从1月1日到12月31日。在Period对象上进行加减,会有和对频度进行位移(shifting)一样的效果:

p + 5
Period('2012', 'A-DEC')
p - 2
Period('2005', 'A-DEC')

如果两个周期有相同的频度,二者的区别就是它们之间有多少个单元(units):

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

固定范围的周期(Regular ranges of periods)可以通过period_range函数创建:

rng = pd.period_range('2000-01-01', '2000-06-03', freq='M')
rng
PeriodIndex(['2000-01', '2000-02', '2000-03', '2000-04', '2000-05', '2000-06'], dtype='int64', freq='M')

PeriodIndex类能存储周期组成的序列,而且可以作为任何pandas数据结构中的轴索引(axis index):

pd.Series(np.random.randn(6), index=rng)
2000-01    0.439035
2000-02   -0.231125
2000-03   -1.085106
2000-04   -1.909902
2000-05    1.478810
2000-06    0.656713
Freq: M, dtype: float64

如果我们有字符串组成的数组,可以使用PeriodIndex类:

values = ['2001Q3', '2002Q2', '2003Q1']
index = pd.PeriodIndex(values, freq='Q-DEC')
index
PeriodIndex(['2001Q3', '2002Q2', '2003Q1'], dtype='int64', freq='Q-DEC')

1 Period Frequency Conversion(周期频度转换)

通过使用asfreq方法,PeriodsPeriodIndex对象能被转换为其他频度。例如,假设我们有一个年度期间(annual period),并且想要转换为月度期间(monthly period),做法非常直观:

p = pd.Period('2007', freq='A-DEC')
p
Period('2007', 'A-DEC')
p.asfreq('M', how='start')
Period('2007-01', 'M')
p.asfreq('M', how='end')
Period('2007-12', 'M')

我们可以认为Period('2007', freq='A-DEC')是某种指向时间跨度的光标,而这个时间跨度被细分为月度期间。可以看下面的图示:

如果一个财政年度(fiscal year)是在1月结束,而不是12月,那么对应的月度期间会不一样:

p = pd.Period('2007', freq='A-JUN')
p
Period('2007', 'A-JUN')
p.asfreq('M', 'start')
Period('2006-07', 'M')
p.asfreq('M', 'end')
Period('2007-06', 'M')

当我们转换高频度为低频度时,pandas会根据 subperiod(次周期;子周期)的归属来决定superperiod(超周期;母周期)。例如,在A-JUN频度中,月份Aug-2007其实是个2008周期的一部分:

p = pd.Period('Aug-2007', 'M')
p.asfreq('A-JUN')
Period('2008', 'A-JUN')

整个PeriodIndex对象或时间序列可以被转换为一样的语义(semantics):

rng = pd.period_range('2006', '2009', freq='A-DEC')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
2006    0.391629
2007    0.497413
2008   -1.685639
2009    0.939885
Freq: A-DEC, dtype: float64
ts.asfreq('M', how='start')
2006-01    0.391629
2007-01    0.497413
2008-01   -1.685639
2009-01    0.939885
Freq: M, dtype: float64

这里,年度周期可以用月度周期替换,对应的第一个月也会包含在每个年度周期里。如果我们想要每年的最后一个工作日的话,可以使用'B'频度,并指明我们想要周期的结尾:

ts.asfreq('B', how='end')
2006-12-29    0.391629
2007-12-31    0.497413
2008-12-31   -1.685639
2009-12-31    0.939885
Freq: B, dtype: float64

2 Quarterly Period Frequencies(季度周期频度)

季度数据经常出现在会计,经济等领域。大部分季度数据都与财政年度结束日(fiscal year end)相关,比如12月最后一个工作日。因此,根据财政年度结束的不同,周期2012Q4也有不同的意义。pandas支持所有12个周期频度,从Q-JANQ-DEC

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

如果是财政年度结束日在一月份,那么2012Q4代表从11月到1月,可以用日频度查看。

p.asfreq('D', 'start')
Period('2011-11-01', 'D')
p.asfreq('D', 'end')
Period('2012-01-31', 'D')

因此,做些简单的周期运算也是可能的,例如,获得每个季度的,第二个到最后一个工作日的,下午4点的时间戳:

p4pm = (p.asfreq('B', 'e') - 1).asfreq('T', 's') + 16 * 60
p4pm
Period('2012-01-30 16:00', 'T')
p4pm.to_timestamp()
Timestamp('2012-01-30 16:00:00')

还可以用period_range产生季度范围数据。运算方法也一样:

rng = pd.period_range('2011Q3', '2012Q4', freq='Q-JAN')
ts = pd.Series(np.arange(len(rng)), index=rng)
ts
2011Q3    0
2011Q4    1
2012Q1    2
2012Q2    3
2012Q3    4
2012Q4    5
Freq: Q-JAN, dtype: int64
new_rng = (rng.asfreq('B', 'e') - 1).asfreq('T', 's') + 16 * 60
ts.index = new_rng.to_timestamp()
ts
2010-10-28 16:00:00    0
2011-01-28 16:00:00    1
2011-04-28 16:00:00    2
2011-07-28 16:00:00    3
2011-10-28 16:00:00    4
2012-01-30 16:00:00    5
dtype: int64

3 Converting Timestamps to Periods (and Back)(时间戳与周期相互转换)

用时间戳作为索引的SeriesDataFrame对象,可以用to_period方法转变为周期:

rng = pd.date_range('2000-01-01', periods=3, freq='M')
ts = pd.Series(np.random.randn(3), index=rng)
ts
2000-01-31    1.556049
2000-02-29   -0.708661
2000-03-31   -0.154767
Freq: M, dtype: float64
pts = ts.to_period()
pts
2000-01    1.556049
2000-02   -0.708661
2000-03   -0.154767
Freq: M, dtype: float64

因为周期是不重复的时间跨度(non-overlapping timespans),一个时间戳只能属于一个有指定频度的单独周期。尽管默认情况下新的PeriodIndex的频度会从时间戳中来推测,但我们也可以自己设定想要的频度。结果中有重复的周期也没有关系:

rng = pd.date_range('1/29/2000', periods=6, freq='D')
rng
DatetimeIndex(['2000-01-29', '2000-01-30', '2000-01-31', '2000-02-01',
               '2000-02-02', '2000-02-03'],
              dtype='datetime64[ns]', freq='D')
ts2 = pd.Series(np.random.randn(6), index=rng)
ts2
2000-01-29    1.115254
2000-01-30   -1.813124
2000-01-31    0.970670
2000-02-01    1.306337
2000-02-02    0.673274
2000-02-03   -0.105436
Freq: D, dtype: float64
ts2.to_period('M')
2000-01    1.115254
2000-01   -1.813124
2000-01    0.970670
2000-02    1.306337
2000-02    0.673274
2000-02   -0.105436
Freq: M, dtype: float64

想转换回时间戳的话,使用to_timestamp:

pts = ts2.to_period()
pts
2000-01-29    1.115254
2000-01-30   -1.813124
2000-01-31    0.970670
2000-02-01    1.306337
2000-02-02    0.673274
2000-02-03   -0.105436
Freq: D, dtype: float64
pts.to_timestamp(how='end')
2000-01-29    1.115254
2000-01-30   -1.813124
2000-01-31    0.970670
2000-02-01    1.306337
2000-02-02    0.673274
2000-02-03   -0.105436
Freq: D, dtype: float64

4 Creating a PeriodIndex from Arrays(从数组中创建一个周期索引)

有固定频度的数据集,有时会在很多列上存储时间跨度信息。例如,在下面的宏观经济数据及上,年度和季度在不同的列:

data = pd.read_csv('../examples/macrodata.csv')
data.head()
year quarter realgdp realcons realinv realgovt realdpi cpi m1 tbilrate unemp pop infl realint
0 1959.0 1.0 2710.349 1707.4 286.898 470.045 1886.9 28.98 139.7 2.82 5.8 177.146 0.00 0.00
1 1959.0 2.0 2778.801 1733.7 310.859 481.301 1919.7 29.15 141.7 3.08 5.1 177.830 2.34 0.74
2 1959.0 3.0 2775.488 1751.8 289.226 491.260 1916.4 29.35 140.5 3.82 5.3 178.657 2.74 1.09
3 1959.0 4.0 2785.204 1753.7 299.356 484.052 1931.3 29.37 140.0 4.33 5.6 179.386 0.27 4.06
4 1960.0 1.0 2847.699 1770.5 331.722 462.199 1955.5 29.54 139.6 3.50 5.2 180.007 2.31 1.19
data.year[:5]
1959Q1    1959.0
1959Q2    1959.0
1959Q3    1959.0
1959Q4    1959.0
1960Q1    1960.0
Freq: Q-DEC, Name: year, dtype: float64
data.quarter[:5]
1959Q1    1.0
1959Q2    2.0
1959Q3    3.0
1959Q4    4.0
1960Q1    1.0
Freq: Q-DEC, Name: quarter, dtype: float64

通过把这些数组传递给PeriodIndex,并指定频度,我们可以把这些合并得到一个新的DataFrame

index = pd.PeriodIndex(year=data.year, quarter=data.quarter, 
                       freq='Q-DEC')
index
PeriodIndex(['1959Q1', '1959Q2', '1959Q3', '1959Q4', '1960Q1', '1960Q2',
             '1960Q3', '1960Q4', '1961Q1', '1961Q2',
             ...
             '2007Q2', '2007Q3', '2007Q4', '2008Q1', '2008Q2', '2008Q3',
             '2008Q4', '2009Q1', '2009Q2', '2009Q3'],
            dtype='int64', length=203, freq='Q-DEC')
data.index = index
data.head()
year quarter realgdp realcons realinv realgovt realdpi cpi m1 tbilrate unemp pop infl realint
1959Q1 1959.0 1.0 2710.349 1707.4 286.898 470.045 1886.9 28.98 139.7 2.82 5.8 177.146 0.00 0.00
1959Q2 1959.0 2.0 2778.801 1733.7 310.859 481.301 1919.7 29.15 141.7 3.08 5.1 177.830 2.34 0.74
1959Q3 1959.0 3.0 2775.488 1751.8 289.226 491.260 1916.4 29.35 140.5 3.82 5.3 178.657 2.74 1.09
1959Q4 1959.0 4.0 2785.204 1753.7 299.356 484.052 1931.3 29.37 140.0 4.33 5.6 179.386 0.27 4.06
1960Q1 1960.0 1.0 2847.699 1770.5 331.722 462.199 1955.5 29.54 139.6 3.50 5.2 180.007 2.31 1.19
data.infl[:5]
1959Q1    0.00
1959Q2    2.34
1959Q3    2.74
1959Q4    0.27
1960Q1    2.31
Freq: Q-DEC, Name: infl, dtype: float64

你可能感兴趣的:(pandas使用教程,pandas,python,matplotlib,开发语言,numpy,django)