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


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

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

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

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

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

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

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

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

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

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

    pd.Series(np.random.randn(6), index=rng)
    
    • 1
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    rng = pd.period_range('2011Q3', '2012Q4', freq='Q-JAN')
    
    • 1
    ts = pd.Series(np.arange(len(rng)), index=rng)
    ts
    
    • 1
    • 2
    2011Q3    0
    2011Q4    1
    2012Q1    2
    2012Q2    3
    2012Q3    4
    2012Q4    5
    Freq: Q-JAN, dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    new_rng = (rng.asfreq('B', 'e') - 1).asfreq('T', 's') + 16 * 60
    
    • 1
    ts.index = new_rng.to_timestamp()
    ts
    
    • 1
    • 2
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

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

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

    rng = pd.date_range('1/29/2000', periods=6, freq='D')
    rng
    
    • 1
    • 2
    DatetimeIndex(['2000-01-29', '2000-01-30', '2000-01-31', '2000-02-01',
                   '2000-02-02', '2000-02-03'],
                  dtype='datetime64[ns]', freq='D')
    
    • 1
    • 2
    • 3
    ts2 = pd.Series(np.random.randn(6), index=rng)
    ts2
    
    • 1
    • 2
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    ts2.to_period('M')
    
    • 1
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

    pts = ts2.to_period()
    pts
    
    • 1
    • 2
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    pts.to_timestamp(how='end')
    
    • 1
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

    data = pd.read_csv('../examples/macrodata.csv')
    data.head()
    
    • 1
    • 2
    yearquarterrealgdprealconsrealinvrealgovtrealdpicpim1tbilrateunemppopinflrealint
    01959.01.02710.3491707.4286.898470.0451886.928.98139.72.825.8177.1460.000.00
    11959.02.02778.8011733.7310.859481.3011919.729.15141.73.085.1177.8302.340.74
    21959.03.02775.4881751.8289.226491.2601916.429.35140.53.825.3178.6572.741.09
    31959.04.02785.2041753.7299.356484.0521931.329.37140.04.335.6179.3860.274.06
    41960.01.02847.6991770.5331.722462.1991955.529.54139.63.505.2180.0072.311.19
    data.year[:5]
    
    • 1
    1959Q1    1959.0
    1959Q2    1959.0
    1959Q3    1959.0
    1959Q4    1959.0
    1960Q1    1960.0
    Freq: Q-DEC, Name: year, dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    data.quarter[:5]
    
    • 1
    1959Q1    1.0
    1959Q2    2.0
    1959Q3    3.0
    1959Q4    4.0
    1960Q1    1.0
    Freq: Q-DEC, Name: quarter, dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

    index = pd.PeriodIndex(year=data.year, quarter=data.quarter, 
                           freq='Q-DEC')
    index
    
    • 1
    • 2
    • 3
    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')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    data.index = index
    
    • 1
    data.head()
    
    • 1
    yearquarterrealgdprealconsrealinvrealgovtrealdpicpim1tbilrateunemppopinflrealint
    1959Q11959.01.02710.3491707.4286.898470.0451886.928.98139.72.825.8177.1460.000.00
    1959Q21959.02.02778.8011733.7310.859481.3011919.729.15141.73.085.1177.8302.340.74
    1959Q31959.03.02775.4881751.8289.226491.2601916.429.35140.53.825.3178.6572.741.09
    1959Q41959.04.02785.2041753.7299.356484.0521931.329.37140.04.335.6179.3860.274.06
    1960Q11960.01.02847.6991770.5331.722462.1991955.529.54139.63.505.2180.0072.311.19
    data.infl[:5]
    
    • 1
    1959Q1    0.00
    1959Q2    2.34
    1959Q3    2.74
    1959Q4    0.27
    1960Q1    2.31
    Freq: Q-DEC, Name: infl, dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    经典算法之直接插入排序法
    Spring Boot 程序启动原理:
    抄写Linux源码(Day19:读取硬盘前的准备工作有哪些?)
    关于Jupyter notebook 创建python3 时进去不能重命名问题及不能编程问题
    Oracle工程师离职并回踩:MySQL糟糕透顶,强烈推荐PostgreSQL
    C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗
    nodejs+vue慢性胃炎健康管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计
    C# 解决从其他地方迁移项目,引用中大多数包是感叹号的问题
    【Tensorflow深度学习】优化算法、损失计算、模型评估、向量嵌入、神经网络等模块的讲解(超详细必看)
    mysql主从复制与读写分离
  • 原文地址:https://blog.csdn.net/weixin_46530492/article/details/134487666