在嵌套 while 循环中更新 pandas 索引和行

Updating pandas index and row in nested while loop

我面临着在使用 pd.iterrows() 生成器的 for 循环中迭代更新 rowindex 的挑战。在下面的示例中,我的 objective 是获取每个连续字母与从索引 0 开始的 first 字母 (A) 之间的距离:

import pandas as pd
import string
 
data = {'letter':['A', 'C', 'D', 'X', 'X', 'Z', 'A', 'E', 'Z', 'Y', 'D', 'B', 'A']}
 
start_idx=df['letter'].iloc[0]

for index, row in df.iloc[1:].iterrows():
    
    dist= abs(string.ascii_uppercase.index(df['letter'].iloc[0]) - \
              string.ascii_uppercase.index(df['letter'].iloc[index]))
              
    print(dist)
2
3
23
23
25
0
4
25
24
3
1
0

这很简单。但是,如果距离超过 5,那么我想开始使用 while 循环将后面的字母与最后一个与前一个字母的距离 <= 5 的“正常”字母进行比较,并附加偏离字母的索引。例如:

import pandas as pd
import string
 
data = {'letter':['A', 'C', 'D', 'X', 'X', 'Z', 'A', 'E', 'Z', 'Y', 'D', 'B', 'A']}
bad_letters = [] 
    

start_idx=df['letter'].iloc[0]
compare_letter = string.ascii_uppercase.index(df['letter'].iloc[0])

for index, row in df.iloc[1:].iterrows():
                                              
    dist= abs(compare_letter-string.ascii_uppercase.index(row['letter']))  
    
    if dist > 5:
                                              
        compare_letter =  string.ascii_uppercase.index(df['letter'][index-1]) #reset compare letter
        abnormal=True

        while abnormal:
            
            bad_letters.append(index)
            dist=abs(compare_letter-string.ascii_uppercase.index(df['letter'][index]))
            index+=1 #increment index
            
            if dist <=5:
                abnormal=False
                compare_letter=string.ascii_uppercase.index(df['letter'][index])
                #?update iterrows index with this index#
                break
            
        else:
            continue
       

输出列表bad_letters 应该是:[3,4,5,8,9]对应于:

-字母索引 X,X,Z 在索引 2
处偏离 D 超过 5 -字母索引 Z,Y 与索引 7 处的字母 E 的偏差超过 5。

上述尝试失败了,我不确定如何以有效使用 iterrows() 和 while 循环的方式正确构建它。如何在 iterrows() 或不同的 pandas 数据帧生成器中使用 while 循环来回答这个基本问题?如何使用打破嵌套 while 循环的索引迭代地“更新”原始 for 循环的 index 和 row?如有任何建议,我们将不胜感激。

您可以在此处利用 less than 和 cumsum 来标记超过阈值的连续值和未超过阈值的先前值。基于此你只需要组> 2,为此你可以将这些组值与组中的第一个值进行比较,并输出那些仍然太远的值。

import pandas as pd
 
data = pd.DataFrame({'letter':['A', 'C', 'D', 'X', 'X', 'Z', 'A', 'E', 'Z', 'Y', 'D', 'B', 'A']})

data['dist'] = data.letter.apply(ord)-ord('A')
data['group']  = data.dist.lt(5).cumsum()


data = data.groupby('group').filter(lambda x: len(x)>1)
data = data.groupby('group').apply(lambda x: (x['dist']-x['dist'].iloc[0])>5).reset_index()

data.loc[data['dist']==True]['level_1'].values

输出

array([3, 4, 5, 8, 9], dtype=int64)