Pandas - 生成按值分组的连续行序列(按时间戳)

Pandas - Generate sequences of consecutive rows (by timestamp) over grouped by values

我在一个 LSTM-based 网络上工作,我需要使用 Pandas 对其他列值的出现序列进行建模,其中每个序列必须受长度限制。

一个实际用例,我有多台机器有日志,日志标有标题和时间戳(为了示例,t1 < t2 < t3 ...),初始数据框如下所示:

d = {'timestamp': ['t1', 't2', 't1', 't3', 't2', 't2', 't1'], 
     'machine': ['M1', 'M2', 'M2', 'M1', 'M2', 'M1', 'M3'], 
     'log': ['A', 'B', 'A', 'C', 'A', 'A', 'B']}

df = pd.DataFrame(d)
print(df.head(7))

  timestamp machine log
0        t1      M1   A
1        t2      M2   B
2        t1      M2   A
3        t3      M1   C
4        t2      M2   A
5        t2      M1   A
6        t1      M3   B

我想要得到的是每台机器的序列最大为 max_len = 2 的数据帧。 所需的输出应如下所示:

max_len = 2

  machine sequence
0      M1   [A, A]  # index from original df: [0, 5]
1      M1   [A, C]  # index from original df: [5, 3]
2      M2   [A, A]  # index from original df: [2, 4]
3      M2   [A, B]  # index from original df: [4, 1]
4      M3      [B]  # index from original df: [6]

序列受 max_len = 2 限制,其元素按 timestamp 排序。

max_len = 3

  machine   sequence
0      M1  [A, A, C]  # index from original df: [0, 5, 3]
1      M2  [A, A, B]  # index from original df: [2, 4, 1]
2      M3        [B]  # index from original df: [6]

序列受 max_len = 3 限制,其元素按 timestamp 排序。

注意: max_len参数是序列长度的上限,我会填充短序列(如M3's)以适应LSTM要求。

注意 2:我实际上按 2 列分组,但为了尽可能减少这个示例,我只包含一列。

到目前为止我尝试了什么:

我一直在使用 PySpark 直到现在,但我通过逐步使用 F.lag 功能而错误地做到了。这留下了许多无用的部分序列,我无法从中识别出需要填充的短序列,而且这种天真的方法很慢而且基本上不是那么好。

w = Window.repartition('machine').orderBy('timestamp')
for i in range(max_len):
   df = df.withColumn(f"log_lag_{i}", F.lag('log', i-1).over(w))

我将不胜感激帮助如何使用 Pandas 处理此问题,我已经尝试了很长时间但失败了。

谢谢!

让我们试试 itertools

import itertools
df=(df.assign(log1=df.groupby('machine')['log'].apply(lambda x: list(sorted(i) for i in (itertools.combinations(x, 2))))# get sorted tuple combinations
              .explode()# Explode them into rows
              .reset_index(drop=True)#Drop index
              .combine_first(df['log'])#Update the new column where there is a null value
              .astype(str)#Convert the lists into string
             ).drop_duplicates(subset=['log','log1'])#drop duplicates
             .drop('timestamp',1)#drop column
   )

   machine log        log1
0      M1   A  ['A', 'C']
1      M2   B  ['A', 'A']
3      M1   C  ['A', 'B']
4      M2   A  ['A', 'B']
5      M1   A  ['A', 'A']
6      M3   B           B