【问题标题】:Insert Data and conditions on timestamp - Pandas Python在时间戳上插入数据和条件 - Pandas Python
【发布时间】:2023-03-27 17:34:01
【问题描述】:

Flag 列对应警报的出现,它的开始和结束与时间戳列对应。

规则:每个开始和后面的结束必须在同一日期

我有这个数据框:

   Flag                     Timestamp
1  begin   2019-10-25 09:39:39.914889
2  end     2019-10-25 09:41:09.103102
3  begin   2019-10-25 10:39:58.352073
4  end     2019-10-25 10:40:06.266782
5  begin   2019-10-25 16:35:22.485574
6  end     2019-10-27 09:50:31.713192
7  begin   2019-10-29 14:04:33.095633
8  end     2019-10-29 14:05:07.639344
9  begin   2019-10-29 14:13:07.924966
10 end     2019-10-29 14:13:08.888890

在第 5 行,我的开始日期为 2019-10-25,结束日期为 2019-10-27,所以这是个问题。

所以我有一个解决方案,但由于我缺乏 pandas python 经验,我无法实现它。

为了遵守规则 1,我想实施 2 种治疗方法:

  • 在这种特定情况下添加缺少的日期
  • 在这种特定情况下添加打开和关闭时间

具体案例:超过几天的警报开始和结束。

我们的例子:

  Flag                 Timestamp
  begin   2019-10-26 07:00:00.00  
  end     2019-10-26 17:00:00.00

  Flag                 Timestamp
  end     2019-10-25 17:00:00.00
  begin   2019-10-27 07:00:00.00

结果必须是:

   Flag                     Timestamp
1  begin   2019-10-25 09:39:39.914889
2  end     2019-10-25 09:41:09.103102
3  begin   2019-10-25 10:39:58.352073
4  end     2019-10-25 10:40:06.266782
5  begin   2019-10-25 16:35:22.485574
6  end     2019-10-25 17:00:00.000000
7  begin   2019-10-26 07:00:00.000000 
8  end     2019-10-26 17:00:00.000000
9  begin   2019-10-27 07:00:00.000000
10 end     2019-10-27 09:50:31.713192
11 begin   2019-10-29 14:04:33.095633
12 end     2019-10-29 14:05:07.639344
13 begin   2019-10-29 14:13:07.924966
14 end     2019-10-29 14:13:08.888890

感谢您的耐心和时间!

【问题讨论】:

    标签: python pandas loops datetime timestamp


    【解决方案1】:

    您可以尝试以下方法:

    • 将数据帧按 2 行分组。这个discussion 解释了如何。

    • 对于每个组:我们检查日期是否为同一天。

      • groupby 的长度让我们知道
      • 如果两个日期是同一天(例如len() == 1
        • 返回两个日期
      • 其他:
        • 我们从开始和结束日期生成daterange
        • 我们用repeat复制每个值
        • 我们使用iloc 删除第一个元素和最后一个元素
        • 因为repeat 重复值,我们使用reset_index 重置索引
        • 然后我们把类型改成pd.Timestamp
        • 对于所有这些日期,因为我们只是将它们转换为pd.Timestamp,我们现在可以使用pd.Timestamp.replace 方法来设置时间(817)。
        • 最后,我们将minmax 日期时间添加到我们的列表中并返回整个列表。

    代码

    # Timestamp type
    df["Timestamp"] = pd.to_datetime(df["Timestamp"])
    # print(df)
    #      Flag                  Timestamp
    # 1   begin 2019-10-25 09:39:39.914889
    # 2     end 2019-10-25 09:41:09.103102
    # 3   begin 2019-10-25 10:39:58.352073
    # 4     end 2019-10-25 10:40:06.266782
    # 5   begin 2019-10-25 16:35:22.485574
    # 6     end 2019-10-27 09:50:31.713192
    # 7   begin 2019-10-26 16:35:22.485574
    # 8     end 2019-10-27 09:50:31.713192
    # 9   begin 2019-10-29 14:04:33.095633
    # 10    end 2019-10-29 14:05:07.639344
    # 11  begin 2019-10-29 14:13:07.924966
    # 12    end 2019-10-29 14:13:08.888890
    
    
    # Our function
    def extends_dates(x):
        if len(x.groupby(x.Timestamp.dt.date)) == 1:
            return x.Timestamp
        else:
            # Create daterange
            d_range = pd.date_range(start=x.Timestamp.dt.date.min(), end=x.Timestamp.dt.date.max()) \
                .repeat(2) \
                .to_series() \
                .iloc[1:-1] \
                .reset_index(drop=True) \
                .apply(pd.Timestamp)
            # Set hours of all date
            news = [d.replace(hour=17) if i % 2 == 0 else d.replace(hour=8)
                    for i, d in enumerate(d_range)]
            # Add min (from dataframe)
            news.insert(0, min(x.Timestamp))
            # Add max date (from dataframe)
            news.append(max(x.Timestamp))
            return pd.Series(news, name="Timestamp")
    
    print(df)
    # Timestamp type
    df["Timestamp"] = pd.to_datetime(df["Timestamp"])
    
    # Starting index to 0
    df.index -= 1
    
    # Create a dataframe from the series
    out = df.groupby(df.index // 2).apply(extends_dates).reset_index(drop=True).to_frame()
    print(out)
    #                     Timestamp
    # 0  2019-10-25 09:39:39.914889
    # 1  2019-10-25 09:41:09.103102
    # 2  2019-10-25 10:39:58.352073
    # 3  2019-10-25 10:40:06.266782
    # 4  2019-10-25 16:35:22.485574
    # 5  2019-10-25 17:00:00.000000
    # 6  2019-10-26 08:00:00.000000
    # 7  2019-10-26 17:00:00.000000
    # 8  2019-10-27 08:00:00.000000
    # 9  2019-10-27 09:50:31.713192
    # 10 2019-10-26 16:35:22.485574
    # 11 2019-10-26 17:00:00.000000
    # 12 2019-10-27 08:00:00.000000
    # 13 2019-10-27 09:50:31.713192
    # 14 2019-10-29 14:04:33.095633
    # 15 2019-10-29 14:05:07.639344
    # 16 2019-10-29 14:13:07.924966
    # 17 2019-10-29 14:13:08.888890
    

    例如,我让您使用np.where 重建flag 列。

    代码

    import numpy as np
    out["Flag"] = np.where(out.index % 2 == 0, "begin", "end")
    print(out)
    #                     Timestamp   Flag
    # 0  2019-10-25 09:39:39.914889  begin
    # 1  2019-10-25 09:41:09.103102    end
    # 2  2019-10-25 10:39:58.352073  begin
    # 3  2019-10-25 10:40:06.266782    end
    # 4  2019-10-25 16:35:22.485574  begin
    # 5  2019-10-25 17:00:00.000000    end
    # 6  2019-10-26 08:00:00.000000  begin
    # 7  2019-10-26 17:00:00.000000    end
    # 8  2019-10-27 08:00:00.000000  begin
    # 9  2019-10-27 09:50:31.713192    end
    # 10 2019-10-26 16:35:22.485574  begin
    # 11 2019-10-26 17:00:00.000000    end
    # 12 2019-10-27 08:00:00.000000  begin
    # 13 2019-10-27 09:50:31.713192    end
    # 14 2019-10-29 14:04:33.095633  begin
    # 15 2019-10-29 14:05:07.639344    end
    # 16 2019-10-29 14:13:07.924966  begin
    # 17 2019-10-29 14:13:08.888890    end
    

    编辑 1

    运行两次不会改变输出。

    # 
    # Timestamp type
    df["Timestamp"] = pd.to_datetime(df["Timestamp"])
    
    # Starting index to 0
    df.index -= 1
    
    # Create a dataframe from the series
    out = df.groupby(df.index // 2).apply(extends_dates).reset_index(drop=True).to_frame()
    
    out_2 = out.groupby(out.index // 2).apply(extends_dates).reset_index(drop=True).to_frame()
    print(out == out_2)
    #     Timestamp
    # 0        True
    # 1        True
    # 2        True
    # 3        True
    # 4        True
    # 5        True
    # 6        True
    # 7        True
    # 8        True
    # 9        True
    # 10       True
    # 11       True
    # 12       True
    # 13       True
    

    【讨论】:

    • with timestamp 我有这个问题:AttributeError: Can only use .dt accessor with datetimelike values
    • 在运行它之前,确保有pandas.datetime对象和df["Timestamp"] = pd.to_datetime(df["Timestamp"])
    • 是的,我试过了,但是当我这样做的时候:---> 12 news.insert(0, min(x.Timestamp)) 13 # 添加最大日期(来自数据框) 14 news.append( max(x.Timestamp)) AttributeError: 'Timestamp' 对象没有属性 'Timestamp'
    • 我重新运行我的答案并且没有任何错误。你确定要运行完整的代码吗?您使用的是哪个 Python 版本?
    • 运行代码 2 次不会改变输出。我无法重现。见编辑 1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 2014-05-10
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多