【问题标题】:Split time series into equally sized "slices" based on one column基于一列将时间序列分成大小相等的“切片”
【发布时间】:2021-12-24 08:48:18
【问题描述】:

我有一个包含 3 个传感器的时间序列,其中一个是告诉我转数的接近开关。

根据机器旋转的速度,此传感器中“光点”的时间距离会发生变化,但是,无论这些光点相距多远,我都想将它们之间发生的所有数据划分为10 个相同大小的块。

我知道确切的行数可能不能被 10 整除,但这没关系。

  Timestamp     Sensor_1  Sensor_2  Sensor_3
1636496284130    60.875    35.946       0
1636496284132    58.467    33.889       0
1636496284134    58.668    37.253       0
1636496284136    57.966    30.540       0
1636496284138    56.712    33.254       0

我希望生成的 DataFrame 有一个额外的 Label 列,其中包含正在发生的时间间隔。

  Timestamp     Sensor_1  Sensor_2  Sensor_3    Label
1636496284130    60.875    35.946       0         A
1636496284132    58.467    33.889       0         A
1636496284134    58.668    37.253       0         A
1636496284136    57.966    30.540       0         A
1636496284138    56.712    33.254       0         A

这是我想要达到的目标的视觉效果。

【问题讨论】:

    标签: python pandas time-series


    【解决方案1】:

    我最终做的是基于 Sensor_3 将 DataFrame 分解为一系列更小的块。由于它先升后降,我所做的只是检测它何时下降并将其视为布尔标志。

    def sensor3flag(val):
        if val >= 0:
            return 0
        else:
            return 1
    
    
    df['Sensor_3_diff'] = df['Sensor_3'].diff().bfill(0).apply(lambda x:sensor3flag(x))
    

    然后我继续创建了一个包含“Sensor_3_diff”== 1 时所有索引的帮助列表。

    df_locs = dfi[dfi['Sensor_3_diff'] == 1]
    
    locList = list(df_locs.index)
    locList.insert(0,0)
    

    最后,我将遍历该索引列表并相应地对主 DataFrame 进行切片,然后根据切片的长度将这些切片中的每一个拆分为 10 个相等的部分。最后将其附加到另一个最终数据帧。

    (labelAssigner()是一个方法,它接受两个参数,并根据它们返回一个标签。第一个参数是记录的索引,第二个是切片DataFrame的大小)

    df_final = pd.DataFrame()
    
    for i in range(0,len(locList)-1):
        sl = dfi.iloc[locList[i]:locList[i+1]]
        sl.reset_index(inplace=True, drop=True)
        sl['Index'] = sl.index
        sl['Label'] = sl['Index'].apply(lambda x:labelAssigner(x, sl.shape[0]))
        df_final = df_final.append(sl)
    

    【讨论】:

      【解决方案2】:

      使用binslabels 转换时间戳to_datetimecut

      这里我使用了 2 个 bin 来存储样本数据:

      df['Label'] = pd.cut(pd.to_datetime(df['Timestamp']), bins=2, labels=list('AB'))
      
      #        Timestamp  Sensor_1  Sensor_2  Sensor_3  Label
      # 0  1636496284130    60.875    35.946         0      A
      # 1  1636496284132    58.467    33.889         0      A
      # 2  1636496284134    58.668    37.253         0      A
      # 3  1636496284136    57.966    30.540         0      B
      # 4  1636496284138    56.712    33.254         0      B
      

      【讨论】:

        【解决方案3】:

        假设 df 是您的输入数据框,并且您想将其拆分为 n_parts(即,为了演示,只有 2 个):

        # Number of equally sized blocks
        n_parts = 2
        
        # Number of blocks needed to achieve that
        n_blocks = df.shape[0] / n_parts
        
        df['Label'] = ['{}'.format(i//n_blocks) for i in range(0, df.shape[0])]
        
        # Output
            Timestamp       Sensor_1    Sensor_2    Sensor_3    Label
        0   1636496284130   60.875       35.946        0        0.0
        1   1636496284132   58.467       33.889        0        0.0
        2   1636496284134   58.668       37.253        0        0.0
        3   1636496284136   57.966       30.540        0        1.0
        4   1636496284138   56.712       33.254        0        1.0
        

        //(楼层运算符)确保在当前 i 小于 n_blocks 时获得相同的标签:

        # n_blocks is 2.5 here, therefore at i=3 we will see the value 1.0
        
        print(['{}'.format(i//n_blocks) for i in range(0, df.shape[0])])
        
        ['0.0', '0.0', '0.0', '1.0', '1.0']
        

        【讨论】:

        • 传感器 3 触发的频率随时间而变化,我已经提出了一个解决方案并将分享它。尽管如此,还是感谢您的帮助。
        猜你喜欢
        • 2020-01-12
        • 2022-10-29
        • 2020-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-10
        • 1970-01-01
        相关资源
        最近更新 更多