I need to assign values to the columns of df
based on conditions. If df.condition>0
, df.result=df.data1
, if df.condition<0
, df.result=df.data2
code show as below:
def main():
import pandas as pd
import numpy as np
condition = {"condition": np.random.randn(200)}
df = pd.DataFrame(condition)
df['data1'] = np.random.randint(1, 100, len(df))
df['data2'] = np.random.randint(1, 100, len(df))
df['result'] = 0
df['result'].loc[df['condition'] > 0] = df[df['condition'] > 0]['data1']
df['result'].loc[df['condition'] < 0] = df[df['condition'] < 0]['data2']
print (df.head(10))
main()
My method will bring SettingWithCopyWarning: .A value is trying to be set on a copy of a slice from a DataFrame.
And is not optimized. It looks like I have a wrong understanding of pd.series.where
. The modified code is as follows:
def main():
condition = {"condition": np.random.randn(200)}
df = pd.DataFrame(condition)
df['data1']=np.random.randint(1,100, len(df))
df['data2']=np.random.randint(1,100, len(df))
df['result']=0
gt=df.condition>0
lt=df.condition<0
df.result.where(gt,df.data2,inplace=True)
df.result.where(lt,df.data1,inplace=True)
print (df.head(10))
return
main()
The result is:
condition data1 data2 result
0 -1.580927 63 23 23
1 -1.549005 94 20 20
2 2.153873 18 83 18
3 -0.115974 31 8 8
4 -0.726009 61 38 38
5 2.039930 96 63 96
6 -1.523605 94 96 96
7 -0.157509 8 4 4
8 -0.166163 11 21 21
9 -0.540077 14 64 64
I just figured out the usage of np.where
:
import pandas as pd
import numpy as np
def main():
condition = {"condition": np.random.randn(200)}
df = pd.DataFrame(condition)
df['data1'] = np.random.randint(1, 100, len(df))
df['data2'] = np.random.randint(1, 100, len(df))
df['result'] = np.where(df['condition'] > 0, df['data1'], df['data2'])
print (df.head(10))
main()
Create boolean masks for your conditions and use them with DataFrame.loc to select the rows on the left-hand-side and the right-hand-side of the assignment.
Boolean Indexing
>>> df.head(15)
data a b data2
0 1.864896 81 30 0
1 -0.059083 81 93 0
2 -0.953324 89 1 0
3 0.367495 2 68 0
4 -1.537818 70 88 0
5 -1.118238 76 35 0
6 -0.017608 46 68 0
7 1.571796 12 95 0
8 0.683234 44 7 0
9 -1.320751 50 42 0
10 -0.463197 19 66 0
11 0.786541 44 32 0
12 -0.171833 28 26 0
13 1.668763 75 7 0
14 0.846662 42 56 0
>>> gt = df.data > 0
>>> lt = df.data < 0
>>> df.loc[gt,'a'] = df.loc[gt,'data2']
>>> df.loc[lt,'b'] = df.loc[lt,'data2']
>>> df.head(15)
data a b data2
0 1.864896 0 30 0
1 -0.059083 81 0 0
2 -0.953324 89 0 0
3 0.367495 0 68 0
4 -1.537818 70 0 0
5 -1.118238 76 0 0
6 -0.017608 46 0 0
7 1.571796 0 95 0
8 0.683234 0 7 0
9 -1.320751 50 0 0
10 -0.463197 19 0 0
11 0.786541 0 32 0
12 -0.171833 28 0 0
13 1.668763 0 7 0
14 0.846662 0 56 0
Using Series.where you have to reverse the logic as it only changes the values where the condition is NOT met.
>>> df.head(10)
data a b data2
0 1.046114 41 66 0
1 0.156532 65 46 0
2 -0.768515 56 36 0
3 0.640834 36 89 0
4 0.008113 39 26 0
5 -0.528028 63 49 0
6 -1.343293 87 94 0
7 1.076804 5 26 0
8 0.172443 9 57 0
9 -0.375729 84 47 0
>>> gt = df.data > 0
>>> lt = df.data < 0
>>> df.b.where(gt,df.data2,inplace=True)
>>> df.a.where(lt,df.data2,inplace=True)
>>> df.head(10)
data a b data2
0 1.046114 0 66 0
1 0.156532 0 46 0
2 -0.768515 56 0 0
3 0.640834 0 89 0
4 0.008113 0 26 0
5 -0.528028 63 0 0
6 -1.343293 87 0 0
7 1.076804 0 26 0
8 0.172443 0 57 0
9 -0.375729 84 0 0
>>>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.