Сшивание массивов в NumPy - PullRequest
1 голос
/ 25 октября 2019

Существует ли простой способ сшивания массивов в numpy, такой, что первое слагаемое в одном массиве складывается с третьим слагаемым в другом массиве? Например:

a = np.array((1,2,3))
b = np.array((2,3,4))

Я бы хотел, чтобы в этом случае был результат (1,2,5,3,4). Я могу сделать это с помощью циклов for, но мне интересно, есть ли простой способ сделать это, используя numpy. Спасибо!

Ответы [ 4 ]

0 голосов
/ 25 октября 2019

Предполагая, что вы хотите суммировать только последний и первый элементы последовательных массивов:

def stitch(arrs, dtype=None):
    if len(arrs) < 2:
        raise ValueError("Not supported")
    res = np.empty(sum(x.size - 1 for x in arrs) + 1, dtype=dtype)
    idx = 0
    res[0] = arrs[0][0]
    for i in range(len(arrs) - 1):
        a, b = arrs[i], arrs[i + 1]
        off = a.size - 1
        res[idx+1:idx+off] = a[1:-1]
        res[idx+off] = a[-1] + b[0]
        idx += off
    res[idx+1:] = arrs[-1][1:]
    return res

В отличие от других ответов, этот позволяет избежать ненужных списков-преобразований / копий и дополнений. :) Обратите внимание, что ответ @ Torben может быть еще быстрее для массивов достаточно малого размера.

0 голосов
/ 25 октября 2019

В одну сторону, используя functools.reduce:

import numpy as np
from functools import reduce

def f(arr1, arr2):
    return [*arr1[:-1], arr1[-1] + arr2[0], *arr2[1:]]

a = np.array((1,2,3))
b = np.array((2,3,4))
c = np.array((10,20,30))

reduce(f, [a,b,c])

Вывод:

[1, 2, 5, 3, 14, 20, 30]
0 голосов
/ 25 октября 2019

Решение

Для пары каждых двух массивов вы можете сделать следующее.

np.hstack([a[:-1], np.array([a[-1], b[0]]).sum(), b[1:]])

Для списка массивов:

Фиктивные данные, которые я использовал здесь, были созданы с кодом, приведенным в конце (самый нижний раздел) этого решения,Вам нужны только следующие две функции для этого.

def array_stitch(a, b):
    c = np.hstack([a[:-1], np.array([a[-1], b[0]]).sum(), b[1:]]) 
    return c

def recursive_array_stitch(array_list):
    c = array_stitch(array_list[0], array_list[1])
    for e in array_list[2:]:
        c = array_stitch(c, e)
    return c

recursive_array_stitch(array_list)

Выход :

array([ 4,  5,  6,  8,  2,  3,  8,  5,  9,  4,  5,  6,  8,  5,  4,  5,  6,
       10,  2])

Здесь array_list задается как:

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

Подробное решение

Только для двух массивов, как показано в постановке задачи вопроса. Для нескольких массивов это может быть использовано рекурсивно, и это было сделано в разделе выше.

import numpy as np

a = np.array((1,2,3))
b = np.array((2,3,4))
c = np.hstack([a[:-1], np.array([a[-1], b[0]]).sum(), b[1:]]) 
c

Выход :

array([1, 2, 5, 3, 4])

Если вы хотите, чтобы это был кортеж: c.tuple() даст вам (1, 2, 5, 3, 4).

Список массивов

См. Решение в начале для списка массивов. Я буду использовать данные, созданные с использованием следующего кода.

# Dummy Data
np.random.seed = 43
start, stop = np.random.randint(1,5,size=8), np.random.randint(3,9,size=8)
array_list = [np.arange(k,k+3) if l<=k else np.arange(k,l) for k,l in zip(start, stop)]
array_list

Выход :

[array([4, 5, 6, 7]),
 array([1, 2, 3, 4]),
 array([4, 5, 6]),
 array([3, 4, 5, 6, 7]),
 array([1, 2]),
 array([3, 4, 5, 6, 7]),
 array([2]),
 array([1, 2])]
0 голосов
/ 25 октября 2019

Я не думаю, что есть простой способ, так как это не кажется обычной операцией.

Если у вас есть известный список входных данных, я бы рекомендовал предварительно распределить результат и затем использовать добавление на местес движущимся срезом:

def stitch(list_of_arrays):
    final_size = sum(len(arr) for arr in list_of_arrays) - len(list_of_arrays) + 1
    out = np.zeros(final_size)
    ofs = 0
    for arr in list_of_arrays:
        out[ofs:ofs+len(arr)] += arr
        ofs += len(arr) - 1
    return out
...