在 Pandas 数据框中查找模式,按行重新排序,并重置索引

问题描述

这是一个多部分问题。我已经为每个单独的部分找到了解决方案,但是当我尝试组合这些解决方案时,我没有得到我想要的结果。

假设这是我的数据框:

df = pd.DataFrame(list(zip([1,3,6,7,8,4],[6,9,5,1])),columns = ['Values','Vals'])
df

    Values  Vals
0     1     6
1     3     7
2     6     7
3     7     9
4     7     5
5     8     3
6     4     1

假设我想在“值”列中找到模式 [6,7]。 我可以使用此处给出的第二个解决方案的修改版本: Pandas: How to find a particular pattern in a dataframe column?

pattern = [6,7]

pat_i = [df[i-len(pattern):i] # Get the index 
 for i in range(len(pattern),len(df)) # for each 3 consequent elements 
 if all(df['Values'][i-len(pattern):i] == pattern)] # if the pattern matched
pat_i

[   Values  Vals
 2       6     7
 3       7     9
 4       7     5]

我发现将范围缩小到索引值的唯一方法如下:

pat_i = [df.index[i-len(pattern):i] # Get the index 
 for i in range(len(pattern),len(df)) # for each 3 consequent elements 
 if all(df['Values'][i-len(pattern):i] == pattern)] # if the pattern matched
pat_i

[RangeIndex(start=2,stop=5,step=1)]

一旦我找到了模式,我想要在原始数据框中做的是将模式重新排序为 [7,6],同时移动整个关联的行。换句话说,通过索引,我想得到如下所示的输出

df.reindex([0,1,4,2,6])

    Values  Vals
0     1     6
1     3     7
3     7     9
4     7     5
2     6     7
5     8     3
6     4     1

然后,最后,我想重置索引,以便所有列中的值都保留在新的重新排序的位置;

    Values  Vals
0     1     6
1     3     7
2     7     9
3     7     5
4     6     7
5     8     3
6     4     1

为了使用 pat_i 作为重新排序的基础,我尝试修改此处给出的第二个解决方案: Python Pandas: How to move one row to the first row of a Dataframe?

target_row = 2
# Move target row to first element of list.
idx = [target_row] + [i for i in range(len(df)) if i != target_row]

但是,我不知道如何利用 pat_i RangeIndex 对象与此代码一起使用它。该解决方案,当我找到它时,将应用于数百个数据帧,每个数据帧都将包含需要在一个地方重新排序的 [6,7] 模式,但在每个数据帧中的位置不同.

感谢任何帮助......我相信必须有一种优雅的、pythonic 的方式来做到这一点,因为它似乎应该是一个足够普遍的挑战。谢谢。

解决方法

我只是重写了你的代码。我将第一个和最后一个索引放在一边,重新排列感兴趣的索引,然后将所有内容放在一个新索引中。然后我只是使用新索引对数据进行重新排序。

import pandas as pd
from pandas import RangeIndex

df = pd.DataFrame(list(zip([1,3,6,7,8,4],[6,9,5,1])),columns = ['Values','Vals'])
pattern = [6,7]
new_order = [1,2,0] # new order of pattern

for i in list(df[df['Values'] == pattern[0]].index):
    if all(df['Values'][i:i+len(pattern)] == pattern):
        pat_i = df[i:i+len(pattern)]
front_ind = list(range(0,pat_i.index[0]))
back_ind = list(range(pat_i.index[-1]+1,len(df)))
pat_ind = [pat_i.index[i] for i in new_order]
new_ind = front_ind + pat_ind + back_ind
df = df.loc[new_ind].reset_index(drop=True)

df
Out[82]: 
   Values  Vals
0       1     6
1       3     7
2       7     9
3       7     5
4       6     7
5       8     3
6       4     1