2

I am still a beginner in python. I am trying to find a common value with if statement,

import pandas as pd

df = pd.read_csv("data.csv")

for n in range(2, len(df)):
    if df.loc[n].isin([2]).any():
        if df.loc[n-1].isin([1]).any():
            print("Yes")

n += 1
A B
1 3
2 3
1 8
1 2
3 5
2 7

I want it to be printed "Yes" if every time 2 is in n and 1 is in n-1 until the end of data. not just if it matches once. If ever 2 is in n and n-1 doesn't have any value 1, then it won't be printed. For example the above table won't be printed as not all 2 in n doesn't have 1 in n-1

7
  • 1
    What's with the n += 1 at the end? If that's there by accident, please edit to remove it. Commented Nov 4 at 17:01
  • 1
    What's the desired output exactly, and for which rows? Please edit to clarify. You can also remove pd.read_csv("data.csv") since that's not relevant to the question; instead it would be better to provide the data in the code. See How to make good reproducible pandas examples. (See also minimal reproducible example.) Commented Nov 4 at 17:10
  • Why are you using a loop in the first place? Are you aware that iteration in Pandas is an anti-pattern? Maybe you don't know how to do the equivalent of n-1? In that case, I can show you. Commented Nov 4 at 17:10
  • 1
    Maybe the simplest way to clarify the output would be to add print("No") for non-matching rows. Speaking of that, there's no need to nest ifs here when you could use and instead. That would save you one level of nesting. Commented Nov 4 at 17:17
  • 1
    After reading the answer, it seems like I totally misunderstood the output you want because your description is unclear. You meant to say "if every time 2 is in n then 1 is in n-1". Commented Nov 4 at 17:21

3 Answers 3

1

i would give a try to this code:

res = (df.loc[df["A"]==2].index-1).isin(df.loc[df["A"]==1].index).all()

then print your dataframe bases on boolean value in res.

Sign up to request clarification or add additional context in comments.

Comments

1

You can solve this efficiently with a vector operation. You need to find:

  • all rows in which there is at least one "2" with eq + any
  • access the previous rows with shift
  • test again for those if any value is "1"
  • check if all such rows are True
out = df.shift()[df.eq(2).any(axis=1)].eq(1).any(axis=1).all()

Output: False

To better understand how this works, let's define the following intermediates:

m1 = df.eq(2).any(axis=1)
m2 = df.shift()[m1].eq(1).any(axis=1)

Which gives us:

   A  B     m1     m2
0  1  3  False    NaN
1  2  3   True   True  # previous values are 1, 3 -> True
2  1  8  False    NaN
3  1  2   True   True  # previous values are 1, 8 -> True
4  3  5  False    NaN
5  2  7   True  False  # previous values are 3, 5 -> False

Comments

1

If you find writing a loop easier to read rather than using some rather esoteric "one-liner" you could do this:

import pandas

df = pandas.read_csv("data.csv")
prev = next(gt := df.itertuples())

for current in gt:
    if (current.A == 2 and prev.A != 1) or (current.B == 2 and prev.B != 1):
        break
    prev = current
else:
    print("Yes")

Note: I have assumed that the range starting from 2 in the OP wasn't intended

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.