使用iloc一次更新几列

时间:2019-05-14 06:38:08

标签: python pandas dataframe

如何以更优化的方式更新一行中的几列?

masks_df.iloc[mask_row.Index, shelf_number_idx] = tags_on_mask['shelf_number'].iloc[0]
masks_df.iloc[mask_row.Index, stacking_layer_idx] = tags_on_mask['stacking_layer'].iloc[0]
masks_df.iloc[mask_row.Index, facing_sequence_number_idx] = tags_on_mask['facing_sequence_number'].iloc[0]

谢谢。

1 个答案:

答案 0 :(得分:2)

使用:

tags_on_mask = pd.DataFrame({
        'A':list('ab'),
         'facing_sequence_number':[30,5],
         'stacking_layer':[70,8],
         'col_2':[5,7],
         'shelf_number':[50,3],
})

print (tags_on_mask)
   A  facing_sequence_number  stacking_layer  col_2  shelf_number
0  a                      30              70      5            50
1  b                       5               8      7             3

np.random.seed(100)
masks_df = pd.DataFrame(np.random.randint(10, size=(5,5)), columns=tags_on_mask.columns)
print (masks_df)
   A  facing_sequence_number  stacking_layer  col_2  shelf_number
0  8                       8               3      7             7
1  0                       4               2      5             2
2  2                       2               1      0             8
3  4                       0               9      6             2
4  4                       1               5      3             4

shelf_number_idx = 1
stacking_layer_idx = 2
facing_sequence_number_idx = 3

pos = [shelf_number_idx, stacking_layer_idx, facing_sequence_number_idx]
cols = ['shelf_number','stacking_layer','facing_sequence_number']

您可以将list传递给iloc函数,并通过select first将column的第一个值转换为numpy数组,但性能并未提高(我认为只有更好的可读代码):

masks_df.iloc[3, pos] = tags_on_mask[cols].values[0, :]

要提高性能,可以使用DataFrame.iat

masks_df.iat[2, shelf_number_idx] = tags_on_mask['shelf_number'].values[0]
masks_df.iat[2, stacking_layer_idx] = tags_on_mask['stacking_layer'].values[0]
masks_df.iat[2, facing_sequence_number_idx] = tags_on_mask['facing_sequence_number'].values[0]

或者:

for i, c in zip(pos, cols):
    masks_df.iat[2, i] = tags_on_mask[c].values[0]

print (masks_df)
   A  facing_sequence_number  stacking_layer  col_2  shelf_number
0  8                       8               3      7             7
1  0                       4               2      5             2
2  2                      50              70     30             8
3  4                      50              70     30             2
4  4                       1               5      3             4

In [97]: %%timeit
    ...: pos = [shelf_number_idx, stacking_layer_idx, facing_sequence_number_idx]
    ...: cols = ['shelf_number','stacking_layer','facing_sequence_number']
    ...: vals = tags_on_mask[cols].values[0, :]
    ...: masks_df.iloc[3, pos] = vals
    ...: 
2.34 ms ± 33.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [98]: %%timeit
    ...: masks_df.iat[2, shelf_number_idx] = tags_on_mask['shelf_number'].values[0]
    ...: masks_df.iat[2, stacking_layer_idx] = tags_on_mask['stacking_layer'].values[0]
    ...: masks_df.iat[2, facing_sequence_number_idx] = tags_on_mask['facing_sequence_number'].values[0]
    ...: 
34.1 µs ± 1.99 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [100]: %%timeit
     ...: for i, c in zip(pos, cols):
     ...:     masks_df.iat[2, i] = tags_on_mask[c].values[0]
     ...: 
33.1 µs ± 250 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)