Pandas DataFrame/Series有几个与时间序列有关的方法。
入门
记住,在每个代码片段的顶部添加 所需的启动代码到每个代码片段的顶部。这个代码段将使本文中的代码能够无误地运行。
所需的启动代码
import pandas as pd
import numpy
在进行任何数据操作之前,需要安装两个新的库。
- 该
[pandas](https://blog.finxter.com/pandas-quickstart/)库实现了对DataFrame的访问/从DataFrame的访问。 - 该库支持多维数组。
[numpy](https://blog.finxter.com/numpy-tutorial/)库支持多维数组和矩阵,此外还有一系列数学函数。
要安装这些库,请导航到IDE终端。在命令提示符下($),执行下面的代码。对于本例中使用的终端,命令提示符是一个美元符号($)。你的终端提示可能不同。
$ pip install pandas
点击键盘上的<Enter> 键,开始安装过程。
$ pip install numpy
按键盘上的<Enter> 键,开始安装过程。
如果安装成功,终端会显示一条信息,说明这一点。
DataFrame asfreq()
asfreq() 方法将一个时间序列转换为一个指定的频率。
该方法的语法如下。
DataFrame.asfreq(freq, method=None, how=None, normalize=False, fill_value=None)
| 参数 | 说明 |
|---|---|
freq | 点击这里查看频率,或者导航到一个IDE并运行。print(pd.tseries.offsets.__all__) |
method | 该参数完成索引系列(非NaN)中的缺失值。可用的选项有: |
-backfill/bfill :最后一个有效观测值到下面的有效观测值。 | |
-pad/ffill :用下面的有效观测值来填补。 |
|
| how | 可用的选项是start 和end 。默认为end 。 |
| normalize | 决定是否将输出指数重置为午夜。 |
| fill_value | 这个参数是应用于缺失值(不是NaN值)的填充值。 |
在这个例子中,五(5)个随机整数在连续日(Daily Frequency)和工作日(Business Day Frequency)生成并显示。
代码 - 例1:
lst = np.random.randint(10,60, size=5)
idx = pd.date_range('1/16/2022', periods=5, freq='D')
series = pd.Series(lst, index= idx)
df = pd.DataFrame({'Series': series})
print(df)
result = df.asfreq(freq='B')
print(result)
- 第[1]行在指定范围内生成五(5)个随机整数,并将其保存到
lst。 - 第[2]行做了以下工作。
- 基于五(5)天的开始日期创建一个索引。
- 频率变为
'D'(每日频率)。 - 输出保存到
idx。
- 第[3]行基于
lst和idx变量创建一个系列。该输出保存到series。 - 第[4]行根据
series变量创建一个数据框架,并将其保存到df。 - 第[5]行将DataFrame输出到终端。
- 第[6]行使用
asfreq()方法,将频率设置为'B'(营业日频率)。这个输出保存到result。 - 第[7]行将结果输出到终端。
输出结果:
df (连续5天)
| 系列 | |
| 2022-01-16 | 13 |
| 2022-01-17 | 15 |
| 2022-01-18 | 19 |
| 2022-01-19 | 42 |
| 2022-01-20 | 26 |
result (5个工作日 - M-F)
| 系列 | |
| 2022-01-17 | 15 |
| 2022-01-18 | 19 |
| 2022-01-19 | 42 |
| 2022-01-20 | 26 |
2022年1月16日不显示在result 表中,因为它是星期天。
选择'B' 作为频率将忽略任何不在周一至周五之间的日期。
DataFrame asof()
asof() 方法根据where 参数中输入的日期,检索并返回DataFrame/系列(非NaN值)的最后一行。
这个方法的语法如下。
DataFrame.asof(where, subset=None)
| 参数 | 参数描述 |
|---|---|
where | 这个参数是一个单一的日期或最后一行返回前的日期阵列。 |
subset | DataFrame列来检查NaN值。 |
在这个例子中,我们传递一个单一的日期。一个日期满足这个要求,并返回相应的值。
代码 - 例1:
nums = np.random.randint(1,50, size=7)
idx = pd.date_range('1/24/2022', periods=7, freq='D')
series = pd.Series(nums, index=idx)
print(series)
result = series.asof('1/27/2022')
print(result)
- 第[1]行在指定的范围内生成七(7)个随机整数,并将其保存到
nums。 - 第[2]行做了以下工作。
- 基于五(5)天的开始日期创建一个索引。
- 频率变为
'D'(每日频率)。 - 输出保存到
idx。
- 第[3]行基于
nums和idx变量创建一个系列。输出保存到series。 - 第[4]行将
series输出到终端。 - 第[5]行检索与指定日期相关的单个值并保存到
result。 - 第[6]行将结果输出到终端。
输出:
df (连续7天)
| 系列 | |
| 2022-01-24 | 10 |
| 2022-01-25 | 34 |
| 2022-01-26 | 31 |
| 2022-01-27 | 25 |
| 2022-01-28 | 35 |
| 2022-01-29 | 41 |
| 2022-01-30 | 49 |
result (2022-01-27)
| 频率: D, dtype: int32 |
| 25 |
在这个例子中,一个包含五(5)行的CSV文件被读入并保存到一个DataFrame。
代码 - 例2:
df = pd.read_csv('data.csv', parse_dates=['date'])
df.set_index('date', inplace=True)
print(df)
result = df['price'].asof(pd.DatetimeIndex(['2022-02-27 09:03:30', '2022-02-27 09:04:30']))
print(result)
- 第[1]行从CSV文件中创建了一个DataFrame,并使用以下方法解析了日期字段
[parse_dates()](https://blog.finxter.com/read-and-write-flat-files-with-pandas/).这个输出保存到df。 - 第[2]行在
date字段上设置DataFrame的索引和[inplace=True](https://blog.finxter.com/python-inplace-or-operator-meaning/). - 第[3]行将DataFrame输出到终端。
- 第[4]行根据指定的日期范围检索价格。输出保存到
result。 - 第[5]行将结果输出到终端。
输出:
df
| 价格 | |
| 日期 | |
| 2022-02-27 09:01:00 | 8.12 |
| 2022-02-27 09:02:00 | 8.33 |
| 2022-02-27 09:03:00 | 8.36 |
| 2022-02-27 09:04:00 | 8.29 |
| 2022-02-27 09:05:00 | 8.13 |
result
| 2022-02-27 09:03:30 | 8.36 |
| 2022-02-27 09:04:30 | 8.29 |
| 名称:价格,dtype:float64 |
DataFrame shift()
shift() ,将指数按选定的周期数移动,并可选择设置时间频率。
这个方法的语法如下。
DataFrame.shift(periods=1, freq=None, axis=0, fill_value=NoDefault.no_default)
periods | 这个参数是要移动的周期数(正/负)。 |
freq | 点击这里查看频率,或者导航到一个IDE并运行。print(pd.tseries.offsets.__all__) |
axis | 如果选择零(0)或指数,则应用于每一列。默认为0(列)。如果是零(1)或列,应用于每一行。 |
fill_value | 这个参数是新缺失值的填充值。默认值取决于dtype 。- 数字: np.nan 。-日期/时间/周期: NaT 。- 扩展dtypes: self.dtype.na_value 。 |
这个例子为三(3)个每日样本生成了七(5)个随机数。运行这段代码时,数据会移动一(1)个索引。移位后的数据被替换为NaN值。
df = pd.DataFrame({'Sample-1': list(np.random.randint(0,100,size=5)),
'Sample-2': list(np.random.randint(0,100,size=5)),
'Sample-3': list(np.random.randint(0,100,size=5))},
index=pd.date_range('2020-01-01', '2020-01-05'))
print(df)
result1 = df.shift(periods=1)
print(result1)
result2 = df.shift(periods=1, fill_value=0)
print(result2)
-
第[1]行做了以下工作。
-
根据五(5)天的开始日期创建一个索引。
-
频率改变为
'D'(每日频率)。 -
输出保存到
idx。 -
创建一个有五(5)个随机整数的三(3)个样本的DataFrame。
-
索引根据指定的日期范围创建。
-
输出保存到
df。
-
-
第[2]行将DataFrame输出到终端。
-
第[3]行将数据移动了一(1)个周期。第一行的数据替换为NaN值。输出保存到
result1。 -
第[4]行将
result1输出到终端。 -
第[5]行将数据移位一(1)个周期,并将填充值设置为零(0)。输出保存为
result2。 -
第[6]行将
result2输出到终端。
输出:
df
| 样本-1 | 样本-2 | 样本-3 | |
| 2020-01-01 | 18 | 85 | 15 |
| 2020-01-02 | 27 | 66 | 4 |
| 2020-01-03 | 78 | 68 | 5 |
| 2020-01-04 | 6 | 77 | 18 |
| 2020-01-05 | 94 | 20 | 82 |
result1
| 样本-1 | 样品-2 | 样品-3 | |
| 2020-01-01 | 钠 | 钠 | 无 |
| 2020-01-02 | 18 .0 | 85.0 | 15.0 |
| 2020-01-03 | 27 .0 | 66.0 | 4.0 |
| 2020-01-04 | 78.0 | 68 .0 | 5.0 |
| 2020-01-05 | 6 .0 | 77.0 | 18.0 |
第一行的值现在显示NaN值。
原始数据框架的最后一行(df)不显示。
result2
| 样本-1 | 样本-2 | 样本-3 | |
| 2020-01-01 | 0 | 0 | 0 |
| 2020-01-02 | 18 .0 | 85.0 | 15.0 |
| 2020-01-03 | 27 .0 | 66.0 | 4.0 |
| 2020-01-04 | 78.0 | 68 .0 | 5.0 |
| 2020-01-05 | 6 .0 | 77.0 | 18.0 |
result1 的NaN值变成了0(0)。
原始DataFrame (df)的最后一行不显示。
DataFrame slice_shift() & tshift()
这些方法已经不再使用了(从v1.2.0版本开始被废弃)。请使用上面显示的shift() 方法来代替。
DataFrame first_valid_index()
first_valid_index() 方法返回第一个非NA值的index ,如果不存在NA值,则返回None 。
这个方法的语法如下。
DataFrame.first_valid_index()
这个方法不包含任何参数。
在这个例子中,Rivers Clothing的定价表有一个问题。他们想找到第一个包含有效价格的索引(小号、中号、大号)。要做到这一点,请运行以下代码。
idx = ['Small', 'Mediun', 'Large']
df = pd.DataFrame({'Tops': [np.nan, np.nan, np.nan],
'Tanks': [np.nan, 13.45, 14.98],
'Pants': [np.nan, 56.99, 94.87]}, index=idx)
print(df)
result = df.first_valid_index()
print(result)
- 第[1]行为DataFrame创建一个索引并将其保存到
idx。 - 第[2]行创建一个不完整库存价格的DataFrame,设置索引,并将其保存到
df。 - 第[3]行将DataFrame输出到终端。
- 第[4]行从DataFrame中检索出第一个有效的(非NA)值,并将索引保存到
result。 - 第[5]行将结果输出到终端。
输出:
df
| 顶部 | 短裤 | 裤子 | |
| 小号 | 纳恩 | 无 | 无 |
| 中号 | 无 | 13.45 | 56.99 |
| 大号 | 无 | 14.98 | 94.87 |
结果:Medium
第一个非NA值出现在Tanks类别下的Medium索引中。
DataFrame last_valid_index()
last_valid_index() 方法返回最后一个非NA值的index ,如果不存在NA值则返回None。
这个方法的语法如下。
DataFrame.last_valid_index()
这个方法不包含任何参数。
在这个例子中,Rivers Clothing的定价表有一个问题。他们想找到最后一个包含有效价格的索引(小号、中号、大号)。
要做到这一点,请运行以下代码。
idx = ['Small', 'Mediun', 'Large']
df = pd.DataFrame({'Tops': [np.nan, np.nan, np.nan],
'Tanks': [np.nan, 13.45, 14.98],
'Pants': [np.nan, 56.99, 94.87]}, index=idx)
print(df)
result = df.last_valid_index()
print(result)
- 第[1]行为DataFrame创建一个索引并将其保存到
idx。 - 第[2]行创建一个不完整库存价格的DataFrame,设置索引,并将其保存到
df。 - 第[3]行将数据框架输出到终端。
- 第[4]行从DataFrame中检索最后一个有效(非NA)值,并将索引保存到
result。 - 第[5]行将结果输出到终端。
输出:
df
| 顶部 | 短裤 | 裤子 | |
| 小号 | 纳恩 | 无 | 无 |
| 中号 | 无 | 13.45 | 56.99 |
| 大号 | 无 | 14.98 | 94.87 |
结果:Large
最后一个非NA值出现在裤子类别下的Large索引中。