Объединение всех массивов внутри ndarray в numpy

#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 не помогает.