TypeError: zip argument #1 must support iteration in Python

Viewed 630

I'm trying to write code to find two indices when a value changes from 0 to 1 and save that value in a variable called idx. Then, the two rows before and after the index should be extracted and processed. The code for extracting the rows is included below:

df1=pd.DataFrame({'A':[1,3,4,7,8,11,1,15,20,15,16,87],
                 'B':[1,3,4,6,8,11,1,19,20,15,16,87],
                 'flag':[0,0,0,0,1,1,1,0,0,1,0,0]})
         
N = 2
s = [x for s, e in zip(idx-N,idx) for x in range(s, e+1)]
df_before_2rows=df1.loc[df1.index.intersection(s)]

This works. But, if I run this in a for-loop that processes each index one-by-one then I get an error:

df1=pd.DataFrame({'A':[1,3,4,7,8,11,1,15,20,15,16,87],
                     'B':[1,3,4,6,8,11,1,19,20,15,16,87],
                     'flag':[0,0,0,0,1,1,1,0,0,1,0,0]})

for item in idx:
    N = 2
    s = [x for s, e in zip(item-N,item) for x in range(s, e+1)]
    df_before_2rows=df1.loc[df1.index.intersection(s)]
TypeError: zip argument #1 must support iteration

Main goal is to get two rows before when flag change from 0 to 1 and process ,and then go next check if flag change from 0 to 1 then do same as above

2 Answers

IIUC, you can choose a different approach using groupby with cumsum of diff:

df = pd.DataFrame({'A':[1,3,4,7,8,11,1,15,20,15,16,87],
                 'B':[1,3,4,6,8,11,1,19,20,15,16,87],
                 'flag':[0,0,0,0,1,1,1,0,0,1,0,0]})

for _, i in df.groupby(df["flag"].shift(1).diff().eq(1).cumsum()):
    if i["flag"].eq(1).any(): # this is done to skip the last group with no flag of 1
        print (i.tail(3))
        # do your thing with i.tail(3)...

EDIT using your original method:

idx = [4,8] # I assume you retrieved the idx already

for item in idx:
    N = 2
    df_before_2rows=df.loc[range(item-N,item+1)]
    print (df_before_2rows)

item is an element of idx; item-N is also just a number, hence the error.

for item in idx:
    N = 2
    s = [x for s, e in zip(item-N,item) for x in range(s, e+1)]

simplifies to:

for item in idx:
    N = 2
    # s = [x for x in range(item-N, item+1)]
    s = list(range(item-N, item+1))
    # s = np.arange(item-N, item+1)
Related