Ну, вы всегда можете рассчитывать на цифры!Итак, вот один из них, использующий манипуляции с массивами, и он подходит для больших наборов данных -
def char_add_at(a, ixs, vals):
an = a.view('i1').reshape(len(a),-1)
vn = vals.view('i1').reshape(len(vals),-1)
s = (vn!=0).sum(1)
vnc = np.bincount(ixs,s).astype(int)
anc = (an!=0).sum(1)
tnc = anc + vnc
r = len(anc)
c = tnc.max()+1
out_ar = np.zeros((r,c), dtype=np.uint8)
out_ar[:,:anc.max()] = an
fill_mask = tnc[:,None] > np.arange(c)
fill_mask &= out_ar==0
out_ar[fill_mask] = vn[vn!=0]
out = out_ar.view('S'+str(c)).ravel()
return out
Примеры выполнения -
In [671]: a = np.array(['a', 'bz', 'cer'])
...: ixs = np.array([0, 1, 1, 2])
...: vals = np.array(['ez', 'fieabcdef', 'gwop', 'H'])
In [672]: char_add_at(a, ixs, vals)
Out[672]: array(['aez', 'bzfieabcdefgwop', 'cerH'], dtype='|S16')
Время -
Случай № 1:Увеличение выборочного набора данных до 100x
In [675]: # Sample setup
...: a = np.array(['a', 'bz', 'cer'])
...: ixs = np.array([0, 1, 1, 2])
...: vals = np.array(['ez', 'fieabcdef', 'gwop', 'H'])
...:
...: # Scale up sample dataset
...: N = 100 # scale up factor
...: a = np.hstack(([a]*N))
...: ixs = (ixs + (ixs.max()+1)*np.arange(N)[:,None]).ravel()
...: vals = np.hstack(([vals]*N))
# @hpaulj's soln
In [676]: %%timeit
...: ao=a.astype(object)
...: vo=vals.astype(object)
...: np.add.at(ao, ixs, vo)
10000 loops, best of 3: 56.3 µs per loop
In [677]: %timeit char_add_at(a, ixs, vals)
10000 loops, best of 3: 72.6 µs per loop
Случай № 2: Увеличение выборочного набора данных до 1000x
# @hpaulj's soln
In [679]: %%timeit
...: ao=a.astype(object)
...: vo=vals.astype(object)
...: np.add.at(ao, ixs, vo)
1000 loops, best of 3: 483 µs per loop
In [680]: %timeit char_add_at(a, ixs, vals)
1000 loops, best of 3: 364 µs per loop
Случай № 3: Увеличение выборочного набора данных до 10000x
# @hpaulj's soln
In [682]: %%timeit
...: ao=a.astype(object)
...: vo=vals.astype(object)
...: np.add.at(ao, ixs, vo)
100 loops, best of 3: 5.28 ms per loop
In [683]: %timeit char_add_at(a, ixs, vals)
100 loops, best of 3: 3.34 ms per loop