#python #numpy
#python #numpy
Вопрос:
У меня есть ndarray, сгенерированный со всеми возможными комбинациями из 3 массивов, подобных этому:
countries = ["AF"... "Zw"]
names = ["name1",... "nameN"]
var_type = ['var1', 'var2', 'var3']
combinations = np.array(np.meshgrid(names, var_type,countries)).T.reshape(-1, 3)
который выдает ndarray со следующим результатом:
array([
['name1', 'var1', 'AF'],
['name1', 'var2', 'AF'],
['name1', 'var3', 'AF'],
...,
['nameN', 'var1', 'ZW'],
['nameN', 'var2', 'ZW'],
['nameN', 'var3', 'ZW']
])
И я хочу объединить каждый отдельный подмассив, чтобы получить новый массив с объединенными значениями, подобными этому:
array([
"name1-var1-AF",
"name1-var2-AF",
"name1-var3-AF",
...,
"nameN-var1-ZW",
"nameN-var2-ZW",
"nameN-var3-ZW"
])
Но единственный способ, который мне пока нравится в Google, — это цикл for, подобный этому:
columns = []
for column in combinations:
columns.append(str('-'.join(column)))
есть ли более векторизованный способ сделать это??
Комментарии:
1. Каков точный dtype? Можете ли вы показать, как именно создается исходный массив? Т.е. MCVE?
2. Отредактировал вопрос о том, как создается массив, спасибо
3. Всегда ли столбцы в
combinations
имеют одинаковое количество символов? или это произвольно? В последнем случае используйте цикл.4. это может измениться, поскольку имена имеют разную длину
5. Тогда вы мало что сможете сделать. Вы можете поиграть с линейными индексами и таким образом отобразить местоположения, но это будет намного медленнее, чем просто выполнение цикла python. Numpy лучше всего работает для элементов одинакового размера, а эти нет.
Ответ №1:
numpy
не ускоряет скомпилированный код для обработки строк — кроме базовой манипуляции с массивом, которая применяется к любому dtype
. Даже np.char
функции используют базовые строковые методы python.
In [12]: countries = ["AF","Zw"]
...: names = ["name1","name2", "nameN"]
...: var_type = ['var1', 'var2', 'var3']
...: combinations = np.array(np.meshgrid(names, var_type,countries)).T.reshape(-1, 3)
In [14]: ['-'.join(row) for row in _]
Out[14]:
['name1-var1-AF',
'name1-var2-AF',
'name1-var3-AF',
'name2-var1-AF',
...
'nameN-var3-Zw']
По сути, это операция со списком. Итерация по спискам выполняется быстрее
In [18]: timeit ['-'.join(row) for row in combinations]
62.3 µs ± 113 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [19]: timeit ['-'.join(row) for row in combinations.tolist()]
6.55 µs ± 31.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [20]: %%timeit alist = combinations.tolist()
...: ['-'.join(row) for row in alist]
...:
...:
2.88 µs ± 3.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
И если я включу время, затраченное на создание combinations
:
In [29]: %%timeit
...: combinations = np.array(np.meshgrid(names, var_type,countries)).T.reshape(-1, 3)
...: ['-'.join(row) for row in combinations]
...:
...:
164 µs ± 925 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
С другой стороны, используя itertools.product
:
In [30]: timeit ['-'.join(tup) for tup in product(names, var_type, countries)]
4.17 µs ± 136 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Это тот случай, когда numpy
не помогает.