首页 > 解决方案 > Python - 在 Pandas Dataframe 中找到最长的连续运行

问题描述

我有一个 pandas 数据框,它具有以下变量:周、产品代码、约束标志(0 或 1 表示产品供应是否受到限制)。

Week    Product_Code    Constraint_Flag
1           A                1
1           B                0
2           A                0
2           B                1
3           A                0
3           B                0
4           A                0
4           B                0
5           A                1
5           B                0    

我想找到供应不受限制的最长时间段,即每个产品代码的最长的 0 字符串。因此,对于产品 AI,想知道最长的字符串从第 3 周开始并持续了 2 周,而对于产品 B,最长的字符串从第 3 周开始并持续了 3 周。

我怎样才能做到这一点?

标签: pythonpandas

解决方案


使用此解决方案仅查找最长的 0 周期,然后使用聚合首先和最后一个进行过滤:

m  = np.concatenate(( [True], df['Constraint_Flag'] != 0, [True] ))
ss = np.flatnonzero(m[1:] != m[:-1]).reshape(-1,2)
s, e = ss[(ss[:,1] - ss[:,0]).argmax()]
pos = df.columns.get_loc('Week')
print (s,e)
4 8

print (df.iloc[s:e])
   Week Product_Code  Constraint_Flag
4     3            A                0
5     3            B                0
6     4            A                0
7     4            B                0

df = df.iloc[s:e].groupby('Product_Code')['Week'].agg(['first','last'])
print (df)
              first  last
Product_Code             
A                 3     4
B                 3     4

但如果需要按组进行比较:

def f(x):
    print (x)
    m  = np.concatenate(( [True], x['Constraint_Flag'] != 0, [True] ))
    ss = np.flatnonzero(m[1:] != m[:-1]).reshape(-1,2)
    s, e = ss[(ss[:,1] - ss[:,0]).argmax()]
    pos = x.columns.get_loc('Week')
    c = ['start','end']
    return pd.Series([x.iat[s, pos], x.iat[e-1, pos]], index=c)

   Week Product_Code  Constraint_Flag
0     1            A                1
2     2            A                0
4     3            A                0
6     4            A                0
8     5            A                1
   Week Product_Code  Constraint_Flag
1     1            B                0
3     2            B                1
5     3            B                0
7     4            B                0
9     5            B                0

df = df.groupby('Product_Code').apply(f)
print (df)
              start  end
Product_Code            
A                 2    4
B                 3    5

推荐阅读