【问题标题】:Pandas Preprocessing: Labelling time series data using 2 other filesPandas 预处理:使用 2 个其他文件标记时间序列数据
【发布时间】:2019-01-23 13:30:45
【问题描述】:

我正在尝试使用另一个文件中的类别对时间序列数据进行分类。 我上传了三个文件的图片,图片链接如下。

在过去的几天里,这一直是我生活的祸根。

我正在尝试创建用于行为识别的标记数据集。我有 2 个 CVS 文件来帮助我标记我的 CSV 文件。

1。数据

Here 是我需要标注的数据框的样子。数据每秒收集 40 次,持续数月。我也有不同个人的所有这些数据,所以我将它们分成每个人,然后分成 1000000 行的文件。 CSV 文件最初有日期、小时、秒、小数秒的单独列,但我将其制成一个时间戳,希望可以将其用作索引,然后执行以下操作:

df['Label'].iloc[starttime:endtime] = "Grooming"

我也在考虑使用 unix 时间戳作为索引。 timestamp的dtype是object。

标签中使用的文件

2。行为状态

Here 是带有每个标签的文件的样子。所以我们可以看到修饰从 11:26:48 开始,到 11:28:32 结束。然而,与动物未被观察时相比,数据存在很大差距。所以我们不能总是从下面获取结束时间。这就是我们最终的数据框的用武之地。

3。观察的开始和结束时间。

Here 是我们的最终数据框。我们有每个焦点观察的开始和结束时间,为我们的循环提供了边界。

我尝试过的。

我最初认为嵌套 for 循环将是可行的方法。从需要标记的文件中复制时间戳数据,制作一个标签列,然后将其设置为 0。

然后我打算从文件 3 中获取开始和结束时间,然后当文件 2 中的时间介于这些时间之间时,对于文件 2 中的每个活动,设置我的系列的标签列。

如上所示,我打算像索引一样使用时间,但是由于文件 1 是 40hz,我不能只在文件 2 和 3 的时间戳上附加一些零,因为每个开头可能没有读数第二。我知道pandas has a between time function,但这需要我将数据分成每天,我不知道该怎么做。

【问题讨论】:

    标签: python pandas dataframe time-series dask


    【解决方案1】:

    在解决这个问题数周后,我设法想出了一个解决方案。但是,此解决方案仅使用 pandas,因此,我将在许多较小的文件上运行它,然后最后将它们组合起来。

    加载数据

    首先我加载数​​据:

    path = '/media/peter/ElementsSE/Labelling3/Small/prepared_collar3_0.csv'
    times = pd.read_csv(path)
    
    path = '/media/peter/Elements SE/Labelling3/Small/3labels.csv'
    labels = pd.read_csv(path)
    
    path = '/media/peter/ElementsSE/Labelling3/Small/3TimesForLabels.csv'
    label_times = pd.read_csv(path)
    

    准备

    加载数据后,我为每个数据制作时间戳:

    labels['Date'] = pd.to_datetime(labels['Date(M/DD/YY)'])
    labels['Timestamp'] = labels.apply(lambda row: str(row['Date'].date()) + ' ' + str(row['Time']),axis=1) 
    #Casting from string to timestamp
    labels['Timestamp'] = pd.to_datetime(labels['Timestamp'])
    
    label_times['Date'] = pd.to_datetime(label_times['Date(M/DD/YY)'])
    label_times['Timestamp'] = label_times.apply(lambda row: str(row['Date'].date()) + ' ' + str(row['Time']),axis=1) 
    #Casting from string to timestamp
    label_times['Timestamp'] = pd.to_datetime(label_times['Timestamp'])
    

    制作包含标签的新列

    确保将我的数据集的类别列设置为无,这样我就可以看到有多少数据被标记了。

    times['behav'] = None
    times.Timestamp = pd.to_datetime(times.Timestamp)
    times.head()
    

    循环文件

    在此之后,我们需要遍历 3 个文件并标记它们:

    #Iterating though labeltimes to get the right start and end times
    for i in range(len(label_times)-1):
        date = label_times.loc[i,'Date']
        focal_start_time = label_times.loc[i,'Timestamp']
        focal_end_time = label_times.loc[i+1,'Timestamp']
    
    
        #Now we iterate though the labels
        day_labels = labels.loc[labels.Date == date].reset_index()
        for j in range(len(day_labels)-1):
            time = day_labels.loc[j,'Timestamp']
            next_time = day_labels.loc[j+1,'Timestamp']
            behav = day_labels.loc[j,'Focal Behavioral States']
    
            if(time.date() == focal_start_time.date()):
    
                #We have data of the same date 
                if(time.time() <= focal_end_time.time()):
                    if(time.time() >= focal_start_time.time()):
    
                        #Our start time is in the time range, now we need to check the end time
                        if(next_time.time() <= focal_end_time.time()):
                            if(next_time.time() >= focal_start_time.time()):
                                times.behav.loc[(times.Timestamp >= time) & (times.Timestamp <= next_time)] = behav
    

    Times 现在是一个带标签的数据集。您可能会发现查看有多少数据标记有什么很有用,我使用的是:

    times.behav.value_counts()
    

    很抱歉,这是针对我的问题非常具体的,希望这将有助于解决类似问题的其他人,如果他们和我一样,请为他们节省几周时间。

    【讨论】:

      【解决方案2】:

      我最近为此类问题编写了一个脚本,当时我标记了 112,00 行神经时间序列数据,并获得了每个事件的开始和结束时间。

      1。将数据加载到脚本中

      加载 (1) 您的时间序列数据,(2) 您的事件标记数据,以及 (3) 您的时间序列数据的采样率(即是否以十进制秒、秒等为单位记录)。

      # Your time series data file name
      data_file_name = 'data_time_series.csv'
      
      # Your time series data csv
      data = pd.read_csv(data_file_name, encoding='utf-8', skiprows=0)
      
      # Your events data
      events = pd.read_csv("event_durations.csv", encoding='utf-8', skiprows=1)
      
      sample_rate = 0.1  #Deci-seconds
      

      2。将开始-完成时间分成一列秒/十进制秒

      此函数只是从您的事件标记数据帧中获取持续时间并将其转换为一列秒/十进制秒(取决于您在第 1 步中输入的采样率)。

      def addRange (events):
          global events_split 
          events_split = pd.DataFrame()
          events = np.array(events)
          row = 0
          for _row in events:
              x = round(events[row,0],1) # Start time
              y = round(events[row,1],1) # End time
              events_split = events_split.append(pd.DataFrame([x]))
              while x < y:
                  x = round((x + sample_rate),1)
                  events_split = events_split.append(pd.DataFrame([x]))
              row = row + 1
          return events_split
      
      addRange(events)
      

      3。将该列表转换为一列 1 和 0

      对于这个函数,我们需要首先创建一个包含时间序列数据的“时间”列的可迭代变量:

      data_time_col = pd.DataFrame([data.iloc[:,0]]) data_time_col = data_time_col.T

      然后,下面的函数使用此变量以及新分解的事件标记数据来创建与时间序列数据中的行完全匹配的 1 和 0 列。

      def addEvents(data_time_col):
          global labels_01_df
          labels_01_df = pd.DataFrame() 
          for i in data_time_col.values:
              if i in events_split.values:
                  labels_01_df = labels_01_df.append([1], ignore_index=True)
              else:
                  labels_01_df = labels_01_df.append([0], ignore_index=True)
          return labels_01_df
      
      addEvents(data_time_col)
      

      4。将 1 和 0 的列写入数据文件中的“标签”列

      最后,我们需要将您的 0 和 1 列表插入您的时间序列数据框中,并将其导出到 csv。 (新列将插入索引 [0] 并推动其他列)。带有标签的新文件将出现在您的目录中,其名称与原始文件相同,但末尾带有“LABELLED”。

      data.insert(loc=0, column="labels", value=labels_01_df)
      data.to_csv(data_file_name + " - LABELLED.csv", index=False)
      

      我希望这会有所帮助。这里还有一些关于这个过程的更多信息:https://medium.com/@lucy.m.rothwell/labelling-time-series-data-in-python-af62325e8f60

      【讨论】:

        猜你喜欢
        • 2016-12-07
        • 1970-01-01
        • 1970-01-01
        • 2020-03-02
        • 2015-07-17
        • 1970-01-01
        • 2021-07-10
        • 1970-01-01
        • 2017-10-23
        相关资源
        最近更新 更多