10

I want if the conditions are true if df[df["tg"] > 10 and df[df["tg"] < 32 then multiply by five otherwise divide by two. However, I get the following error

ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

d = {'year': [2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001],
     'day': [1, 2, 3, 4, 1, 2, 3, 4,],
     'month': [1, 1, 1, 1, 2, 2, 2, 2],
     'tg': [10, 11, 12, 13, 50, 21, -1, 23],
     'rain': [1, 2, 3, 2, 4, 1, 2, 1]}
df = pd.DataFrame(data=d)
print(df)


[OUT]

   year  day  month  tg  rain
0  2001    1      1  10     1
1  2001    2      1  11     2
2  2001    3      1  12     3
3  2001    4      1  13     2
4  2001    1      2  50     4
5  2001    2      2  21     1
6  2001    3      2  -1     2
7  2001    4      2  23     1

df["score"] = (df["tg"] * 5) if ((df[df["tg"] > 10]) and (df[df["tg"] < 32])) else (df["tg"] / 2) 

[OUT]
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

What I want

   year  day  month  tg  rain   score
0  2001    1      1  10     1    5
1  2001    2      1  11     2    55
2  2001    3      1  12     3    60
3  2001    4      1  13     2    65
4  2001    1      2  50     4    25
5  2001    2      2  21     1    42
6  2001    3      2  -1     2    0.5
7  2001    4      2  23     1    46

3
  • 1
    You are looking for where: pandas.pydata.org/docs/reference/api/… Commented Nov 4, 2021 at 16:12
  • Although not the most efficient solution, it is also worth being aware of map to apply a scalar function to each element: df["score"] = df["tg"].map(lambda x: x*5 if 10<x<32 else x/2) Commented Nov 4, 2021 at 16:15
  • 1
    Your expected output seems wrong for indices 5, 6 and 7. Commented Nov 4, 2021 at 16:19

5 Answers 5

5

You can use where:

df['score'] = (df['tg']*5).where(df['tg'].between(10, 32), df['tg']/5)
Sign up to request clarification or add additional context in comments.

1 Comment

Very minor but just helping OP match their expected output. I had the same idea btw =D
4

Use np.where:

# do you need `inclusive=True`? Expected output says yes, your logic says no
mask = df['tg'].between(10,32, inclusive=False)
df['score'] = df['tg'] * np.where(mask, 5, 1/2)

 # or
 # df['score'] = np.where(mask, df['tg'] * 5, df['tg']/2)

Output:

   year  day  month  tg  rain  score
0  2001    1      1  10     1    5.0
1  2001    2      1  11     2   55.0
2  2001    3      1  12     3   60.0
3  2001    4      1  13     2   65.0
4  2001    1      2  50     4   25.0
5  2001    2      2  21     1  105.0
6  2001    3      2  -1     2   -0.5
7  2001    4      2  23     1  115.0

Comments

2

Let try to fix it with for loop

[x * 5 if (x > 10 and x < 32) else (x / 2) for x in df['tg']]
Out[64]: [5.0, 55, 60, 65, 25.0, 105, -0.5, 115]

Comments

2

You can use df.loc

mask = (df["tg"] > 10) & (df["tg"] < 32)
df.loc[mask, "score"] = df["tg"] * 5
df.loc[~mask, "score"] = df["tg"] / 2

Comments

1

For a more detailed explanation of your error message, have a look at this from the pandas' docs.

Another option, in addition to the already excellent answers, is the case_when function from pyjanitor, which could be a helpful abstraction, especially for multiple conditions, or you probably need to preserve Pandas extension dtypes:

# pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
import pandas as pd
import janitor

df.case_when(
      df.tg.gt(10) & df.tg.le(32), # condition
      df.tg.mul(5), # result if True
      df.tg.div(2), # result if False
      column_name='score')
 
   year  day  month  tg  rain  score
0  2001    1      1  10     1    5.0
1  2001    2      1  11     2   55.0
2  2001    3      1  12     3   60.0
3  2001    4      1  13     2   65.0
4  2001    1      2  50     4   25.0
5  2001    2      2  21     1  105.0
6  2001    3      2  -1     2   -0.5
7  2001    4      2  23     1  115.0

More examples can be found here

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.