我需要在一个名为'month'
的列中替换为基于另一列'step_name'
的同一列中的值。如果df.step_name.str.contains('step1')
我想使用'month'
的值,其中df.step_name.str.contains('step2')
。我使用了df.loc[]
,但是它只是用month
删除了'step1'
的值。
for i in set(df['id']): df.loc[(df.id.str.contains(i))&(df.step_name.str.contains('step1')),'month'] = df.loc[(df.id.str.contains(i))&(df.step_name.str.contains('step2')),'month']
假设源数据帧包含:
id step_name month
0 10 step1 January
1 10 step2 March
2 12 step1 February
3 12 step2 April
4 14 step1 May
以便在具有索引0和2的行中(step_name =='step1')month列应更新为下一行的值(step_name =='step2',相同的[[id)。
为此,请运行:df.set_index('id', inplace=True)
df.update(df[df.step_name == 'step2']['month'])
df.reset_index(inplace=True)
结果是:
id step_name month 0 10 step1 March 1 10 step2 March 2 12 step1 April 3 12 step2 April 4 14 step1 May
请注意,实际上使用各自的[[id更新两行,但如果行中带有step_name =='step2',则什么都不会更改。我认为,我的解决方案比您的循环更pandasonic每个update
id
的单独更新。# Your code.
is_step1 = new_df.step_name.str.contains('step1')
is_step2 = new_df.step_name.str.contains('step2')
for i in set(df['id']):
is_id = df.id.str.contains(i)
df.loc[is_id & is_step1, 'month'] = df.loc[is_id & is_step2, 'month']
您使用两个互相影响的蒙版。
'''
mask1 mask2 => df[mask1] df[mask2]
1 0 value1 NaN -> value1 = NaN
0 1 NaN value2
0 0 NaN NaN
0 0 NaN NaN
'''
如果您改为使用数组,则pandas会将值映射为该数组以填充在作业的左侧...
new_df.loc[is_id & is_step1, 'month'] = new_df.loc[is_id & is_step2, 'month'].values
...这就是发生的情况:
'''
mask1 mask2 => df[mask1] df[mask2].values
1 0 value1 value2 -> value1 = value2
0 1 NaN
0 0 NaN
0 0 NaN
'''
现在,例如,如果您想交换step1和step2的月份...
# N.B. I don't say it is best practice, but it works!
new_df = df.sort_values('id')
is_step1 = new_df.step_name.str.contains('step1')
is_step2 = new_df.step_name.str.contains('step2')
c = df.loc[is_step1, 'month'].values
new_df.loc[is_step1, 'month'] = new_df.loc[is_step2, 'month'].values
new_df.loc[is_step2, 'month'] = c
我相信Valdi_Bo的解决方案是最好的。接受他的回答。 ;)