We have data, which is represented below:
import pandas as pd
import numpy as np
d = {'shift_city_id': [1, 1,2,3,3,3,1], 'closest_city_id': [np.nan, np.nan,np.nan,np.nan,np.nan,np.nan,np.nan]}
df = pd.DataFrame(data=d)
df
shift_city_id closest_city_id
0 1 NaN
1 1 NaN
2 2 NaN
3 3 NaN
4 3 NaN
5 3 NaN
6 1 NaN
The goal is to input specific values in a cell with particular city_id, one by one. So I try this:
df.loc[lambda x: (x['shift_city_id']==3),'closest_city_id'].iloc[0]=3
df.loc[lambda x: (x['shift_city_id']==3),'closest_city_id'].iloc[1]=4
df.loc[lambda x: (x['shift_city_id']==3),'closest_city_id'].iloc[2]=5
and get no change at all in dataframe, np.nan is still there. While the result should be:
shift_city_id closest_city_id
0 1 NaN
1 1 NaN
2 2 NaN
3 3 3
4 3 4
5 3 5
6 1 NaN
What can solve the problem?
CodePudding user response:
You could do:
df.loc[lambda x: (x['shift_city_id']==3),'closest_city_id'] = [3,4,5]
which gives the wanted output:
To understand the different behaviour of the assignation, I defer to these detailed answers
CodePudding user response:
Dynamic so that you could do more than one id/values set at a time:
ids = [3]
id_values = {3: [3, 4, 5]}
df['closest_city_id'] = df[df['shift_city_id'].isin(ids)]['shift_city_id'].replace(id_values)
Output:
shift_city_id closest_city_id
0 1 NaN
1 1 NaN
2 2 NaN
3 3 3.0
4 3 4.0
5 3 5.0
6 1 NaN
CodePudding user response:
Here lambda is not necessary, you can compare column df['shift_city_id']
and because 3 rows matched is possible assign list with length 3
:
df.loc[df['shift_city_id']==3,'closest_city_id'] = [3,4,5]
print (df)
shift_city_id closest_city_id
0 1 NaN
1 1 NaN
2 2 NaN
3 3 3.0
4 3 4.0
5 3 5.0
6 1 NaN