python-3.x - 如何通过在 Pandas 中使用多个列来提取时间序列中的模式?
问题描述
我有一个包含来自不同时间戳的不同度量的 DataFrame 看起来像这样:
data=np.array([["2019-08-08 08:29", 29.9, 4., 1.],["2019-08-08 08:30", 30.1, 4., 1.],["2019-08-08 08:31", 30.1, 0., 0.], ["2019-08-08 08:32", 27.2, 1., 0.], ["2019-08-08 08:33", 15.0, 2., 0.], ["2019-08-08 08:34", 15.1, 2., 0.], ["2019-08-08 08:35", 19.1, 2., 1.], ["2019-08-08 08:36", 26.7, 2., 2.], ["2019-08-08 08:37", 30.0, 2., 3.], ["2019-08-08 08:38", 30.1, 2., 3.], ["2019-08-08 08:39", 29.9, 0., 0.], ["2019-08-08 08:40", 25.1, 1., 0.], ["2019-08-08 08:41", 23.4, 2., 0.], ["2019-08-08 08:42", 15.1, 3., 0.]])
df = pd.DataFrame(data[:, 1:4], index=data[:, 0], columns=["A", "B", "C"], dtype='float64')
df.index = pd.to_datetime(df.index)
print(df.to_string())
A B C
2019-08-08 08:29:00 29.9 4.0 1.0
2019-08-08 08:30:00 30.1 4.0 1.0
2019-08-08 08:31:00 30.1 0.0 0.0
2019-08-08 08:32:00 27.2 1.0 0.0
2019-08-08 08:33:00 15.0 2.0 0.0
2019-08-08 08:34:00 15.1 2.0 0.0
2019-08-08 08:35:00 19.1 2.0 1.0
2019-08-08 08:36:00 26.7 2.0 2.0
2019-08-08 08:37:00 30.0 2.0 3.0
2019-08-08 08:38:00 30.1 2.0 3.0
2019-08-08 08:39:00 29.9 0.0 0.0
2019-08-08 08:40:00 25.1 1.0 0.0
2019-08-08 08:41:00 23.4 2.0 0.0
2019-08-08 08:42:00 15.1 3.0 0.0
我想找到定义如下的数据中的所有模式:
- 模式的开始:B 列的值达到 0。
- 模式结束:C 列达到最大值。
以下是由水平条表示的模式的值图:
plt.figure(figsize=(10, 8))
plt.subplot(211)
plt.plot(df.index, df.A)
plt.axvline(x="2019-08-08 08:31", color="red")
plt.axvline(x="2019-08-08 08:37", color='red')
plt.axvline(x="2019-08-08 08:39", color='green')
plt.subplot(212)
plt.plot(df.index, df.B)
plt.plot(df.index, df.C)
plt.axvline(x="2019-08-08 08:31", color="red")
plt.axvline(x="2019-08-08 08:37", color='red')
plt.axvline(x="2019-08-08 08:39", color='green')
plt.show()
红色条锁定一个模式,绿色条是新模式的开始。
为了识别模式,我首先创建了两列来查找模式的开头和结尾:
df["New_pattern"] = (df['B'] == 0) & (df['B'].shift(1) != 0)
df["End_pattern"] = (df['C'] > df['C'].shift(1)) & (df['C'] == df['C'].shift(-1))
print(df.New_pattern.loc[df.New_pattern == True].to_string())
2019-08-08 08:31:00 True
2019-08-08 08:39:00 True
print(df.End_pattern.loc[df.End_pattern == True].to_string())
2019-08-08 08:37:00 True
所以这给了我很好的结果,可以在这个示例数据中找到模式的开始和结束。虽然在我的真实数据中,我的模式结束比模式开始多两倍。我认为这是因为我在两个新模式之间的 C 列的数据中有几个平坦区域,但我现在没有找到任何证据。
您还应该知道,每当测量 B 达到 0 时,测量 C 也达到 0,否则这些值不能减少,所以我知道两个新模式之间存在最大值。
我有两个问题:
- 如何在两个新模式时间戳之间找到结束模式,而不是使用 wole 数据框?它将通过将 true 设置为两个新模式之间第一次达到最大值的时间戳来计算。
- 如何使用 New_pattern 和 End_pattern 列提取数据模式?
解决方案
我找到了解决问题的方法,但我不知道它是否是最有效的。
我创建了一个 DataFrame,用于存储新模式开始的时间戳,并将 -1 移到另一列中。
df_pattern = df.New_pattern.loc[df.New_pattern == True].reset_index()["index"].rename("New_pattern").to_frame()
df_pattern["Next_new"] = df_pattern.shift(-1)
我通过为这个新数据帧的每一行选择新数据帧的两列的时间戳之间的所有行来计算第一个数据帧的 C 列的 idxmax。这给了我每个模式的结束。
def getEndPattern(row):
if not pd.isnull(row[0]) and not pd.isnull(row[1]):
return df.C.loc[row[0]:row[1]].idxmax()
else:
return np.nan
df_pattern["End_pattern"] = df_pattern.apply(lambda row: getEndPattern(row), axis=1)
print(df_pattern.to_string())
New_pattern Next_new End_pattern
0 2019-08-08 08:31:00 2019-08-08 08:39:00 2019-08-08 08:37:00
1 2019-08-08 08:39:00 NaT NaT
然后我在我的第一个 DataFrame 中创建一个由 nan 填充的列来存储当前数字的数量。我遍历包含模式时间戳的 DataFrame 的行以选择这些时间戳之间的行,然后放置正确数量的模式:
df["number_pattern"] = np.nan
for index, row in df_pattern.iterrows():
if not pd.isnull(row[1]):
df["number_pattern"].loc[row[0]:row[2]] = index
print(df.to_string())
A B C New_pattern number_pattern
2019-08-08 08:29:00 29.9 4.0 1.0 False NaN
2019-08-08 08:30:00 30.1 4.0 1.0 False NaN
2019-08-08 08:31:00 30.1 0.0 0.0 True 0.0
2019-08-08 08:32:00 27.2 1.0 0.0 False 0.0
2019-08-08 08:33:00 15.0 2.0 0.0 False 0.0
2019-08-08 08:34:00 15.1 2.0 0.0 False 0.0
2019-08-08 08:35:00 19.1 2.0 1.0 False 0.0
2019-08-08 08:36:00 26.7 2.0 2.0 False 0.0
2019-08-08 08:37:00 30.0 2.0 3.0 False 0.0
2019-08-08 08:38:00 30.1 2.0 3.0 False NaN
2019-08-08 08:39:00 29.9 0.0 0.0 True NaN
2019-08-08 08:40:00 25.1 1.0 0.0 False NaN
2019-08-08 08:41:00 23.4 2.0 0.0 False NaN
2019-08-08 08:42:00 15.1 3.0 0.0 False NaN
2019-08-08 08:42:00 15.1 3.0 0.0 False NaN
2019-08-08 08:42:00 18.1 3.0 1.0 False NaN
2019-08-08 08:42:00 15.1 3.0 1.0 False NaN
现在,当我想做一些分析时,我将按模式的数量进行分组,或者使用带有时间戳的 DataFrame。
这是我的解决方案,但我很乐意欢迎其他使用 Pandas 或 Python 技巧的建议,这些建议可能会让你更容易、更快或只是以不同的方式看到不同的方法。
推荐阅读
- javascript - 在 JSX 标签内的 map 中反应 if 语句
- javascript - 循环通过过滤器函数内部的第二个数组
- angular - Angular7 ControlValueAccesor 作为 FormArray
- python - 如何解决变量中的变量?
- python - Python Socket 编程简单的 Web 服务器,试图从服务器访问一个 html 文件
- amazon-web-services - AWS MediaConvert - 拼接纵向和横向视频
- android - Android Native:CMake 链接错误:未定义对 GL 函数的引用 - 即使包含并链接了 EGL 和 GLESv3
- wakanda - 瓦坎达工作室遭遇端口冲突
- java - 来自java的错误值被插入mysql
- javascript - 为什么我不能使用 Axios 通过 GitHub REST API 进行身份验证?