在Python中操纵时间序列数据
一个单一主体(实体)在不同时间间隔内的观察(活动)的集合被称为时间序列数据。在指标的情况下,时间序列是等距的,在事件的情况下,时间序列是不等距的。我们可以在这个Pandas模块中为每条记录添加日期和时间,也可以获取数据帧记录,发现特定日期和时间范围内的数据。
生成一个日期范围
pd.date_range()方法被用来创建一个日期范围,日期范围的频率为每月。
# importing pandas
import pandas as pd
# creating a date range
Date_range = pd.date_range(start='1/12/2020', end='20/5/2021', freq='M')
print(Date_range)
print(type(Date_range))
print(type(Date_range[0]))
输出:
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
'2020-05-31', '2020-06-30', '2020-07-31', '2020-08-31',
'2020-09-30', '2020-10-31', '2020-11-30', '2020-12-31',
'2021-01-31', '2021-02-28', '2021-03-31', '2021-04-30'],
dtype='datetime64[ns]', freq='M')
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
对时间戳数据的操作
在pd.DataFrame()方法的帮助下,日期范围被转换为一个数据框架。使用to_datetime()方法将列转换为DateTime。info()方法给出数据框架的信息,如果有任何空值和列的数据类型。
# importing pandas
import pandas as pd
# creating a date range
Date_range = pd.date_range(start='1/12/2020', end='20/5/2021', freq='M')
# creating a Dataframe
Data = pd.DataFrame(Date_range, columns=['Date'])
# converting the column to datetime
Data['Date'] = pd.to_datetime(Data['Date'])
print(Data.info())
输出:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 16 entries, 0 to 15
Data columns (total 1 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Date 16 non-null datetime64[ns]
dtypes: datetime64[ns](1)
memory usage: 256.0 bytes
将数据从一个字符串转换成一个时间戳
如果我们有一个类似于DateTime的字符串数据列表,我们可以先用pd.DataFrame()方法将其转换为数据框架,然后用pd.to_datetime()方法将其转换成DateTime列。
# importing pandas
import pandas as pd
# creating string data
string_data = ['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
'2020-05-31', '2020-06-30', '2020-07-31', '2020-08-31',
'2020-09-30', '2020-10-31', '2020-11-30', '2020-12-31',
'2021-01-31', '2021-02-28', '2021-03-31', '2021-04-30']
Data = pd.DataFrame(string_data, columns=['Date'])
Data['Date'] = pd.to_datetime(Data['Date'])
print(Data.info())
输出:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 16 entries, 0 to 15
Data columns (total 1 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Date 16 non-null datetime64[ns]
dtypes: datetime64[ns](1)
memory usage: 256.0 bytes
None
根据我们的字符串值的格式,我们可以将它们转换成DateTime。在这种情况下,可以使用datetime.strptime()函数
# importing pandas
import pandas as pd
from datetime import datetime
# string data
string_data = ['May-20-2021', 'May-21-2021', 'May-22-2021']
timestamp_data = [datetime.strptime(x, '%B-%d-%Y') for x in string_data]
print(timestamp_data)
Data = pd.DataFrame(timestamp_data, columns=['Date'])
print(Data.info())
输出:
[datetime.datetime(2021, 5, 20, 0, 0), datetime.datetime(2021, 5, 21, 0, 0), datetime.datetime(2021, 5, 22, 0, 0)]
<class ‘pandas.core.frame.DataFrame’>
RangeIndex: 3 entries, 0 to 2
Data columns (total 1 columns):
# Column Non-Null Count Dtype
— —— ————– —–
0 Date 3 non-null datetime64[ns]
dtypes: datetime64[ns](1)
memory usage: 152.0 bytes
对时间序列数据进行切片和索引
本例中导入了CSV文件,并使用pd.to_timestamp()方法将字符串数据的列转换为DateTime。这个特定的列被设置为索引,帮助我们对数据进行相应的切分和索引。 data.loc['2020-01-22'][:10]
对’2020-01-22’这一天的数据进行索引,结果被进一步切分以返回这一天的前10个观测值。
# importing pandas
import pandas as pd
# reading csv file
data = pd.read_csv('covid_data.csv')
# converting string data to datetime
data['ObservationDate'] = pd.to_datetime(data['ObservationDate'])
# setting index
data = data.set_index('ObservationDate')
print(data.head())
# indexing and slicing through the dataframe
print(data.loc['2020-01-22'][:10])
输出:
Unnamed: 0 Province/State ... Deaths Recovered
ObservationDate ...
2020-01-22 0 Anhui ... 0.0 0.0
2020-01-22 1 Beijing ... 0.0 0.0
2020-01-22 2 Chongqing ... 0.0 0.0
2020-01-22 3 Fujian ... 0.0 0.0
2020-01-22 4 Gansu ... 0.0 0.0
[5 rows x 7 columns]
Unnamed: 0 Province/State ... Deaths Recovered
ObservationDate ...
2020-01-22 0 Anhui ... 0.0 0.0
2020-01-22 1 Beijing ... 0.0 0.0
2020-01-22 2 Chongqing ... 0.0 0.0
2020-01-22 3 Fujian ... 0.0 0.0
2020-01-22 4 Gansu ... 0.0 0.0
2020-01-22 5 Guangdong ... 0.0 0.0
2020-01-22 6 Guangxi ... 0.0 0.0
2020-01-22 7 Guizhou ... 0.0 0.0
2020-01-22 8 Hainan ... 0.0 0.0
2020-01-22 9 Hebei ... 0.0 0.0
[10 rows x 7 columns]
在这个例子中,我们将数据从’2020-01-22’切分到’2020-02-22’。
# importing pandas
import pandas as pd
from datetime import datetime
# reading csv file
data = pd.read_csv('covid_data.csv')
# converting string data to datetime
data['ObservationDate'] = pd.to_datetime(data['ObservationDate'])
# setting index
data = data.set_index('ObservationDate')
# indexing and slicing through the dataframe
print(data.loc['2020-01-22':'2020-02-22'])
输出:
Unnamed: 0 Province/State ... Deaths Recovered
ObservationDate ...
2020-01-22 0 Anhui ... 0.0 0.0
2020-01-22 1 Beijing ... 0.0 0.0
2020-01-22 2 Chongqing ... 0.0 0.0
2020-01-22 3 Fujian ... 0.0 0.0
2020-01-22 4 Gansu ... 0.0 0.0
... ... ... ... ... ...
2020-02-22 2169 San Antonio, TX ... 0.0 0.0
2020-02-22 2170 Seattle, WA ... 0.0 1.0
2020-02-22 2171 Tempe, AZ ... 0.0 0.0
2020-02-22 2172 Unknown ... 0.0 0.0
2020-02-22 2173 NaN ... 0.0 0.0
[2174 rows x 7 columns]
对不同时间段的各种总量/汇总统计的时间序列数据进行重新取样。
要对时间序列数据进行重新取样,可以使用pandas resample()函数。它是一种时间序列频率转换和重采样的便利技术。如果对象有类似DateTime的索引,调用者必须将类似DateTime的系列/索引的标签给on/level关键字参数。
# importing pandas
import pandas as pd
from datetime import datetime
# reading csv file
data = pd.read_csv('covid_data.csv')
# converting string data to datetime
data['ObservationDate'] = pd.to_datetime(data['ObservationDate'])
# setting index
data = data.set_index('ObservationDate')
# resampling data according to year
data = data.resample('Y').mean()
print(data)
输出:
Unnamed: 0 Confirmed Deaths Recovered
ObservationDate
2020-12-31 96232.5 39696.116550 1160.959453 24659.893368
2021-12-31 249447.0 163315.277678 3514.893386 93925.632661
计算一个滚动的统计数字,如滚动平均数
用Pandas创建的数据框架。rolling()方法允许你计算滚动窗口。计算滚动窗口的想法最常被用于信号处理和时间序列数据。换句话说,我们每次取一个大小为k的窗口,并对其进行一些数学运算。一个大小为k的窗口标志着在同一时间显示k个连续的数值。在最简单的例子中,所有的’k’值都是同等权重的。在下面的例子中,窗口大小为5。
# importing pandas
import pandas as pd
from datetime import datetime
# reading csv file
data = pd.read_csv('covid_data.csv')
# converting string data to datetime
data['ObservationDate'] = pd.to_datetime(data['ObservationDate'])
data['Last Update'] = pd.to_datetime(data['Last Update'])
# setting index
data = data.set_index('ObservationDate')
data = data[['Last Update', 'Confirmed']]
data['rolling_sum'] = data.rolling(5).sum()
print(data.head())
输出:
Last Update Confirmed rolling_sum
ObservationDate
2020-01-22 2020-01-22 17:00:00 1.0 NaN
2020-01-22 2020-01-22 17:00:00 14.0 NaN
2020-01-22 2020-01-22 17:00:00 6.0 NaN
2020-01-22 2020-01-22 17:00:00 1.0 NaN
2020-01-22 2020-01-22 17:00:00 0.0 22.0
处理缺失的数据
在前面的例子中,rolling_sum列有Nan值,所以我们可以用这个数据来演示如何处理缺失数据。
当CSV文件包含空值时,空值在数据框中显示为NaN。Fillna()处理并让用户用自己的值替换NaN值,类似于pandas dropna()函数维护和删除数据框中的Null值。通过在fillna()中传递backfill作为方法参数值来完成对数据帧中缺失值的逆向填充。Fillna()通过传递fill作为方法参数值,以正向方式填充数据框架中的缺失值。
# importing pandas
import pandas as pd
from datetime import datetime
# reading csv file
data = pd.read_csv('covid_data.csv')
# converting string data to datetime
data['ObservationDate'] = pd.to_datetime(data['ObservationDate'])
data['Last Update'] = pd.to_datetime(data['Last Update'])
# setting index
data = data.set_index('ObservationDate')
data = data[['Last Update', 'Confirmed']]
data['rolling_sum'] = data.rolling(5).sum()
print(data.head())
# dealing with missing data
data['rolling_backfilled'] = data['rolling_sum'].fillna(method='backfill')
print(data.head(5))
输出:
Last Update Confirmed rolling_sum
ObservationDate
2020-01-22 2020-01-22 17:00:00 1.0 NaN
2020-01-22 2020-01-22 17:00:00 14.0 NaN
2020-01-22 2020-01-22 17:00:00 6.0 NaN
2020-01-22 2020-01-22 17:00:00 1.0 NaN
2020-01-22 2020-01-22 17:00:00 0.0 22.0
Last Update Confirmed rolling_sum rolling_backfilled
ObservationDate
2020-01-22 2020-01-22 17:00:00 1.0 NaN 22.0
2020-01-22 2020-01-22 17:00:00 14.0 NaN 22.0
2020-01-22 2020-01-22 17:00:00 6.0 NaN 22.0
2020-01-22 2020-01-22 17:00:00 1.0 NaN 22.0
2020-01-22 2020-01-22 17:00:00 0.0 22.0 22.0
Unix/epoch时间的基础知识
人们在处理时间序列数据时可能会遇到Unix时间的时间值。自1970年1月1日(星期四)00:00:00协调世界时(UTC)以来的秒数,被称为Unix时间,有时也被称为大纪元时间。Unix时间帮助我们破译时间戳,这样我们就不会被时区、夏令时和其他因素混淆。
在下面的例子中,我们使用pd.to_timestamp()方法将纪元时间转换为时间戳。如果我们想把UTC中的时间转换成某个特定的时区,可以使用tz_localize()和tz.convert()方法。在下面的例子中,我们将其转换为 “欧洲/柏林 “时区。
# importing pandas
import pandas as pd
from datetime import datetime
# epoch time
epoch = 1598776989
# converting to timestamp
timestamp = pd.to_datetime(epoch, unit='s')
print(timestamp)
# converting it to a particular time zone
print(timestamp.tz_localize('UTC').tz_convert('Europe/Berlin'))
输出:
2020-08-30 08:43:09
2020-08-30 10:43:09+02:00