Векторизация форматирования строки в массиве NumPy - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть два целочисленных массива, которые я хочу объединить для каждого элемента в один массив строк вида 'a[i]_b[i]'.То есть у меня есть

import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

, и я хочу получить массив

result = np.array(['1_4', '2_5', '3_6'])

Я могу легко сделать это с помощью списка:

result = np.array(['{}_{}'.format(a[i], b[i]) for i in range(len(a))])

Номои массивы a и b очень длинные, и это слишком медленно.Есть ли способ сделать это через пустые звонки?Что-то, что hstack -иш?Я могу получить это далеко:

result np.hstack([a.resahpe(len(a), 1), b.reshape(len(b), 1)])

, что дает мне

np.array([[1, 4]
          [2, 5]
          [3, 6]])

Наверняка должен быть простой способ добраться отсюда до желаемого результата ...

Редактировать:

Использование двух вызовов defchararray кажется даже медленнее, чем понимание списка, но frompyfunc эффективно ...

>>> import timeit
>>> t = Timer("""['{}_{}'.format(a[i], b[i]) for i in range(len(b))]""", setup="""import numpy as np; a = np.random.randn(10000); b=np.random.randn(10000)""")
>>> t.timeit(1000)
22.310123541974463

>>> t2 = Timer("""np.core.defchararray.add(np.core.defchararray.add(a.astype(str),'_'), b.astype(str))""", setup="""import numpy as np; a = np.random.randn(10000); b=np.random.randn(10000)""")
>>> t2.timeit(1000)
28.489826270961203

>>> t3 = Timer("""fv(a,b)""", setup='import numpy as np; a = np.random.randn(10000); b=np.random.randn(10000); fv =  np.frompyfunc("{}_{}".format, 2, 1)')
>>> t3.timeit(1000)
15.455791965010576

И здесь это зависит от длины a и b (кажется стабильным):

enter image description here

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018
fv = np.frompyfunc("{}_{}".format, 2, 1)
result = fv(a, b)  # array(['1_4', '2_5', '3_6'], dtype=object)

В зависимости от времени это примерно 1/3 времени выполнения списка и преобразования в np.array.

In [2]: a = np.arange(100000)

In [3]: b = np.arange(100000) + a.size

In [4]: fv = np.frompyfunc("{}_{}".format, 2, 1)

In [5]: def f(a, b): return np.array(["{}_{}".format(a,b) for a,b in zip(a,b)], dtype=object)

In [6]: %timeit f(a,b)
370 ms ± 12.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [7]: %timeit fv(a,b)
137 ms ± 1.48 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
0 голосов
/ 14 декабря 2018

Вы можете использовать defchararray.add

import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.core.defchararray.add(a.astype(str),'_')
c = np.core.defchararray.add(c,b.astype(str))
print(c) #['1_4' '2_5' '3_6']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...