如何用 pandas 处理不同时间序列的变长?
Posted
技术标签:
【中文标题】如何用 pandas 处理不同时间序列的变长?【英文标题】:How to deal with different time series of variable length with pandas? 【发布时间】:2020-09-01 16:30:29 【问题描述】:我有数据矩阵,其中每一行都被视为时间序列,但长度不同。看起来是这样的:
在文本中:
0 1 2 3 4 5 6 7 8 9
0 12 32 45 67 89 54 23.0 56.0 78.0 98.0
1 34 76 34 89 34 3 NaN NaN NaN NaN
2 76 34 54 12 43 78 56.0 NaN NaN NaN
3 76 56 45 23 43 45 67.0 76.0 67.0 8.0
4 87 9 9 0 89 90 6.0 89.0 NaN NaN
5 23 90 90 32 23 34 56.0 9.0 56.0 87.0
6 23 56 34 3 5 8 7.0 6.0 98.0 NaN
7 32 23 34 6 65 78 67.0 87.0 89.0 87.0
8 12 23 34 32 43 67 45.0 NaN NaN NaN
9 343 76 56 7 8 9 4.0 5.0 8.0 68.0
我曾尝试使用带有代码的 pandas 读取数据:
timeseries=pd.read_excel('timeseries.xlsx',header=None)
###### timeseries ##############
print(timeseries)
然后我想将每一行数据矩阵传递给时间序列分析模型,该模型将为每个时间序列生成一个值,在传递所有时间序列后,我将得到一个特征向量。
我曾尝试使用以下代码实现:
features=[]
for i,j in timeseries.iterrows():
row=timeseries.iloc[i]
model=AR(row.values)
model_fit=model.fit()
yhat=model_fit.predict(len(row),len(row))
features.append(yhat)
fvector=pd.DataFrame(features)
print(fvector)
但我认为这是错误
MissingDataError: exog 包含 inf 或 nans
据我所知,它发生在分析方法限制 NaN 值并引发此错误时,但根据我的情况,每个时间序列都需要被视为分析方法的独立输入,并且应该读取到最后一个实际值每一行。
我该如何解决这个问题?
【问题讨论】:
请不要发布您的数据图片,分享可以复制的实际数据。 完成,感谢您的建议。 在应用模型之前填充缺失值。许多时间序列模型不适用于 NaN 等缺失值。 不,无论如何我都无法插入或插补数据...是否有可能我独立解析每一行,以便 NaN 不会被 pandas 标记? 【参考方案1】:您需要删除 NaN 并将它们替换为 0 或其他内容:
timeseries.fillna(0, inplace=True)
print(timeseries)
features=[]
for i,j in timeseries.iterrows():
row=timeseries.iloc[i]
model=AR(row.values)
model_fit=model.fit()
yhat=model_fit.predict(len(row),len(row))
features.append(yhat)
fvector=pd.DataFrame(features)
print(fvector)
0
0 100.704274
1 0.000000
2 0.000000
3 -23.468840
4 19.943124
5 37.442981
6 5.771667
7 105.138431
8 0.000000
9 237.903666
【讨论】:
不能用任何值替换 NaN。是否有可能我读取每一行的值,直到其中出现 NaN?【参考方案2】:您可以使用 NumPy 并将缺失值输入为np.NaN
。
然后您可以将数据读取为 NumPy 数组,转置它(因为在 pandas 中,时间序列应该是一列而不是一行),将其转换为 DataFrame,设置 DatetimeIndex 并从那里获取。
例如:
import numpy as np
import pandas as pd
data = np.asarray([[12, 32, 45, 67, 89, 54, 23.0, 56.0, 78.0, 98.0],
[34, 76, 34, 89, 34, 3, np.NaN, np.NaN, np.NaN, np.NaN],
[76, 34, 54, 12, 43, 78, 56.0, np.NaN, np.NaN, np.NaN],
[76, 56, 45, 23, 43, 45, 67.0, 76.0, 67.0, 8.0],
[87, 9, 9, 0, 89, 90, 6.0, 89.0, np.NaN, np.NaN],
[23, 90, 90, 32, 23, 34, 56.0, 9.0, 56.0, 87.0],
[23, 56, 34, 3, 5, 8, 7.0, 6.0, 98.0, np.NaN],
[32, 23, 34, 6, 65, 78, 67.0, 87.0, 89.0, 87.0],
[12, 23, 34, 32, 43, 67, 45.0, np.NaN, np.NaN, np.NaN],
[343, 76, 56, 7, 8, 9, 4.0, 5.0, 8.0, 68.0]])
df = pd.DataFrame(data.T)
df.index = pd.DatetimeIndex(pd.date_range('2020-05-15', periods=10, freq='d'))
df
0 1 2 3 4 5 6 7 8 9
2020-05-15 12.0 34.0 76.0 76.0 87.0 23.0 23.0 32.0 12.0 343.0
2020-05-16 32.0 76.0 34.0 56.0 9.0 90.0 56.0 23.0 23.0 76.0
2020-05-17 45.0 34.0 54.0 45.0 9.0 90.0 34.0 34.0 34.0 56.0
2020-05-18 67.0 89.0 12.0 23.0 0.0 32.0 3.0 6.0 32.0 7.0
2020-05-19 89.0 34.0 43.0 43.0 89.0 23.0 5.0 65.0 43.0 8.0
2020-05-20 54.0 3.0 78.0 45.0 90.0 34.0 8.0 78.0 67.0 9.0
2020-05-21 23.0 NaN 56.0 67.0 6.0 56.0 7.0 67.0 45.0 4.0
2020-05-22 56.0 NaN NaN 76.0 89.0 9.0 6.0 87.0 NaN 5.0
2020-05-23 78.0 NaN NaN 67.0 NaN 56.0 98.0 89.0 NaN 8.0
2020-05-24 98.0 NaN NaN 8.0 NaN 87.0 NaN 87.0 NaN 68.0
详情请见pandas Time Series documentation.
如果模型函数确实不接受任何缺失值,您可能不得不以某种方式猜测它们。这当然会影响模型的可靠性。请参阅pandas documentation,尤其是df.fillna() 和Wikipedia article on Imputation。
如果适合您的模型,您还可以从上述数据框中提取没有缺失值的单个时间序列。例如。第二栏:
df[1].dropna()
2020-05-15 34.0
2020-05-16 76.0
2020-05-17 34.0
2020-05-18 89.0
2020-05-19 34.0
2020-05-20 3.0
Freq: D, Name: 1, dtype: float64
【讨论】:
【参考方案3】:您的示例并未提供所有需要的详细信息,例如你写了 与AR无关。
据我了解,您的软件在某些行中抱怨 NaN 值, 所以你应该:
从每一行中消除 NaN 值, 仅在处理之后。这次关于执行速度的另一个细节是,如果你遍历行,那么:
循环的第二个控制值已经包含当前行, 因此没有必要再按索引再读一遍。所以改变你的代码做如下的事情:
for i, row in timeseries.iterrows():
row = row.dropna()
print(f'i: row.size:2 row.values')
# Any further processing of "row"
当然,print 仅用于演示目的。 将其放入代码的目标版本中。
我怀疑是否用零替换 NaN 值(如建议 在另一个答案中)是正确的方法,因为它可能会“破坏” 你的模型中有一些东西。
编辑
如果您只想处理当前行的“初始”部分,即 正如您在评论中所要求的,直到第一个 Nan(不包括), 将对 dropna() 的调用替换为:
row = row[row.isna().cumsum() == 0]
要检查它是如何工作的,请替换例如带索引的行中的最后一个 NaN 1 具有一些有限值并观察这一行的结果。
【讨论】:
我是否可以读取每一行的值,直到其中出现 NaN?如果是,那么解决方法是什么?以上是关于如何用 pandas 处理不同时间序列的变长?的主要内容,如果未能解决你的问题,请参考以下文章