Night Walker
Night Walker

Reputation: 21280

Updating several columns at once using iloc

How I can update several columns of a row in more optimized way ?

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]

Thanks.

Upvotes: 0

Views: 155

Answers (1)

jezrael
jezrael

Reputation: 862731

Use:

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']

You can pass list to iloc function and convert first values of column to numpy array with select first, but performance is not increase (only better readable code in my opinion):

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

For improve performance is possible use 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]

Or:

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)

Upvotes: 2

Related Questions