从循环 if 语句子集熊猫时间序列数据帧

Posted

技术标签:

【中文标题】从循环 if 语句子集熊猫时间序列数据帧【英文标题】:Subset pandas timeseries dataframe from looping if statement 【发布时间】:2019-10-11 04:55:09 【问题描述】:

请让我知道我的问题的标题是否准确 - 我认为我需要一个循环 if 语句来解决以下问题 - 我是 Python 和一般编程的新手,所以不知道术语是否正确正确。

我正在使用 Spyder,正在做一个研究项目。

我需要在现有数据框 (df) 中创建一个新变量,该变量提供以下逻辑:

在时间 T1(数字 1 在 e1 列中第一次出现)和时间 T2(在 e1 中第二次出现)之间,如果在 T1 和 T2 之间记录了任何变量(e2 或 e3)的 1 或者 T1 和 T2 之间的 v1 的值大于 1,然后在 T1 和 T2 之间名为“结果”的新列中放置一个 1。

在时间 T2(数字 1 在 e1 列中第二次出现)和时间 T3(在 e1 中第三次出现 1)之间,如果任何变量(e2 或 e3)在 T2 和 T3 之间记录为 1 或者 T2 和 T3 之间的 v1 的值大于 1,然后在 T2 和 T3 之间名为“结果”的新列中放置一个 1。

在T3和T4之间等等等等

根据上述内容,我将根据“结果”中为 1 的所有行创建数据子集,以供进一步分析。

重新创建 df 的一小部分:

import pandas as pd
import numpy as np
import datetime


df = pd.DataFrame('e1' : [1,np.nan,np.nan,1,np.nan,1,np.nan,np.nan,1,np.nan,np.nan,1,np.nan],
                    'e2' : [np.nan,1,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan],
                    'e3' : [np.nan,np.nan,np.nan,np.nan,1,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan],
                    'v1' : [1,1,1,1,1,1,1,1,1,1.2,1.5,1,1],,
                        index=pd.date_range('2019-05-02T00:00:00', '2019-05-02T01:00:00', freq='5T'))

结果应该是:

'result' : [1,1,1,1,1,np.nan,np.nan,np.nan,np.nan,1,1,np.nan,np.nan]

我希望这是有道理的。

谢谢!

编辑 31.05.2019

建议的解决方案适用于大多数情况,但严重失败:

我已编辑示例数据以包含一个实例,其中在 00:25:00 在 e1 和 e2 中都有观察。

import pandas as pd
import numpy as np
import datetime

df = pd.DataFrame('e1' : [1,np.nan,np.nan,1,np.nan,1,np.nan,np.nan,1,np.nan,np.nan,1,np.nan],
                    'e2' : [np.nan,1,np.nan,np.nan,np.nan,1,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan],
                    'e3' : [np.nan,np.nan,np.nan,np.nan,1,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan],
                        index=pd.date_range('2019-05-02T00:00:00', '2019-05-02T01:00:00', freq='5T'))

问题

我遇到的问题是建议的解决方案是在 00:25:00 和 00:40:00 之间报告结果,我希望结果不包括这个。我希望代码分析 e1 列中 1 之间的时间,不包括 e1 中观察的时间。

我希望这是有道理的......

【问题讨论】:

【参考方案1】:

这可以通过 masking 和 groupby 来完成:

# if there is an event at that time
events = df[['e2','e3']].notna().any(axis=1)

# if v1 > 1 at given time
v1g1 = df['v1'].gt(1)

# mask
mask = v1g1 | events

# group the events by e1 
df['result'] = mask.groupby(df.e1.fillna(0).cumsum()).transform('any')

# if you want 1 and NaN:
df['result'] = np.where(mask.groupby(df.e1.fillna(0).cumsum()).transform('any'),
                        1, np.nan)

输出是TrueFalse,而不是1, NaN

                        e1      e2      e3      v1      result
2019-05-02 00:00:00     1.0     NaN     NaN     1.0     True
2019-05-02 00:05:00     NaN     1.0     NaN     1.0     True
2019-05-02 00:10:00     NaN     NaN     NaN     1.0     True
2019-05-02 00:15:00     1.0     NaN     NaN     1.0     True
2019-05-02 00:20:00     NaN     NaN     1.0     1.0     True
2019-05-02 00:25:00     1.0     NaN     NaN     1.0     False
2019-05-02 00:30:00     NaN     NaN     NaN     1.0     False
2019-05-02 00:35:00     NaN     NaN     NaN     1.0     False
2019-05-02 00:40:00     1.0     NaN     NaN     1.0     True
2019-05-02 00:45:00     NaN     NaN     NaN     1.2     True
2019-05-02 00:50:00     NaN     NaN     NaN     1.5     True
2019-05-02 00:55:00     1.0     NaN     NaN     1.0     False
2019-05-02 01:00:00     NaN     NaN     NaN     1.0     False

【讨论】:

嗨,这不起作用。我有一个问题,在我的数据中,如果我在 e1 中的事件同时有一个观察值(在 e2 或 e3 中),它会将其包含在最终结果中。我需要代码在 T1 和 T2 之间的时间工作,不包括 T1 和 T2。我已经对我的原始问题添加了一个编辑。谢谢。 我已使用更新的数据示例编辑了原始问题,以演示我遇到的问题。问题是解决方案包括 T1 和 T2,但我需要解决方案不包括 T1 和 T2,而是使用 T1 和 T2 之间的时间。 抱歉,我的结果列显示不正确。我会编辑。

以上是关于从循环 if 语句子集熊猫时间序列数据帧的主要内容,如果未能解决你的问题,请参考以下文章

For循环子集化的熊猫数据框

基于不同数据帧中的日期时间的子集熊猫数据帧

使用 for 循环、if 循环和 zip 迭代 panda 数据帧和列表

Numpy:从熊猫数据帧创建可变长度序列

从大熊猫数据帧由总和行以15个分钟垃圾箱数据帧的时间序列

熊猫滚动加权平均值