1

I have a dataframe. I want to set all values that are less than x, in rows that have a certain parameter value, to a new value.

I try this, but nothing happens to my dataframe.

   df_data = {'A': [4, 4, 5, 5],
               'B': [4, 4, 4, 5],
               'C': [4, 5, 5, 5],
               'Bool': [True, True, False, False]}
    test_df = pd.DataFrame(df_data, columns=['A', 'B', 'C', 'Bool'])
    test_df[test_df.iloc[:, :-1] < 5][test_df['Bool'] == True] = 99
    print(test_df)

I expect some elements in the test_df to have value 99.

muzzex
  • 157
  • 2
  • 16

2 Answers2

1

If want chain boolean DataFrame with & for bitwise AND is necessary convert it to numpy array (N, 1) and then set new values with DataFrame.mask:

m = (test_df.iloc[:, :-1] < 5).values & test_df['Bool'].values[:, None]
print (m)
[[ True  True  True]
 [ True  True False]
 [False False False]
 [False False False]]

test_df.iloc[:, :-1] = test_df.iloc[:, :-1].mask(m, 99)
print(test_df)
    A   B   C   Bool
0  99  99  99   True
1  99  99   5   True
2   5   4   5  False
3   5   5   5  False
jezrael
  • 822,522
  • 95
  • 1,334
  • 1,252
  • I get error message when creating m: ValueError: Unable to coerce to DataFrame, shape must be (4, 3): given (4L, 1L) – muzzex Sep 03 '19 at 14:53
  • m = (test_df.iloc[:, :-1] < 5) & (pd.DataFrame(pd.np.tile((test_df['Bool'].values[:, None] == True), (1, 3)))).values test_df.iloc[:, :-1] = test_df.iloc[:, :-1].mask(m, 99) – muzzex Sep 03 '19 at 15:05
  • @muzzex can you test `m = (test_df.iloc[:, :-1].values < 5) & test_df['Bool'].values[:, None] print (m)` – jezrael Sep 03 '19 at 15:35
  • 1
    That last comment also work. Need the ".values". Thanks jezrael for your help! – muzzex Sep 04 '19 at 05:58
0

This works:

m = (test_df.iloc[:, :-1] < 5) & (pd.DataFrame(pd.np.tile((test_df['Bool'].values[:, None] == True), (1, 3)))).values
test_df.iloc[:, :-1] = test_df.iloc[:, :-1].mask(m, 99)
muzzex
  • 157
  • 2
  • 16