I changed slightly your sample data, to have one positive result:
df = pd.DataFrame(data=[
[ 334, 290, 3350.0 ],
[ 334, 291, 3350.5 ],
[ 334, 292, 3360.1 ],
[ 335, 292, 3360.1 ],
[ 335, 292, 3360.1 ],
[ 333, 290, 3351.0 ],
[ 335, 290, 3352.5 ],
[ 335, 291, 3333.1 ],
[ 335, 291, 3333.1 ]], columns=['x', 'y', 'z'])
Then, for efficiency reason, I defined the following function:
def roll_win(a, win):
shape = (a.shape[0] - win + 1, win, a.shape[1])
strides = (a.strides[0],) + a.strides
return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
It generates a 3-D table, where 2nd and 3rd dimension are "rolling
windows" from the source Numpy array a. The size of window is win,
sliding vertically.
This way, processing of consecutive windows requires a loop running along
the first axis of the generated table (see below).
Due to usage of as_strided function it runs significantly quicker than
any "ordinary" Python loop (compare execution time with other solutions).
I couldn't use rolling windows provided by Pandas, because they were
created to compute some statistics, not for calling any user function
on the whole content of the current window.
Then I call this function:
tbl = roll_win(df.values, 7)
Note that Numpy array must have a single element type, so this
type is "generalized" to float because one source column is of
float type.
Then we have preparation steps for a loop processing each rolling window:
res = [] # Result container
idx = 0 # Rolling window index
The rest of the program is the loop:
while idx < len(tbl):
tt = tbl[idx] # Get the current rolling window (2-D)
r0 = tt[0] # Row 0
# Condition
cond = not((r0 == tt[1]).all() and (r0 == tt[3]).all()\
and (r0 == tt[5]).all()) and tt[0][0] < tt[2][0]\
and tt[0][0] > tt[3][0]
if cond: # OK
# print(idx)
# print(tt)
res.extend(tt) # Add to result
idx += 7 # Skip the current result
else: # Failed
idx += 1 # Next loop for the next window
In the "positive" case, I decided to start the next loop from the row
following the current match (idx += 7), to avoid possible partially
overlapping sets of source rows.
If you don't want this feature, add 1 do idx in both cases.
For demonstration purpose, you can uncomment test printouts above.
The only remaining thing is to create the target DataFrame, from rows
collected in res:
df2 = pd.DataFrame(data=res, columns=['x', 'y', 'z'], dtype=int)
Note that dtype=int will be obeyed only for x and y columns,
because values in z column have fractional part.