комбинация numpy 2d массив - PullRequest
1 голос
/ 30 марта 2019

Предположим, у меня есть два массива:

a = np.array(
[[0, 1],
 [2, 3],
 [4, 5],
 [6, 7]])

b = np.array(
[[2, 3],
 [6, 7],
 [0, 1],
 [4, 5]])

Как видите, один массив - это просто shuffle другого.Мне нужно объединить эти два массива, чтобы сформировать третий массив, c, такой как:

  • первая часть массива c (до случайного индекса i) состоит из элементов изпервая часть массива a (до индекса i).Следовательно, c[:i] == a[:i] должен возвращать значение True.
  • Остальная часть массива c заполняется значениями из массива b, которые еще не находятся внутри массива c, в том же порядке, в котором они появляютсяв.

Учитывая, что для индекса i установлено значение , равное 2 , требуемый вывод для вышеуказанных массивов a и b в коде должен быть:

> c
[[0, 1],
 [2, 3],
 [6, 7],
 [4, 5]]

Массив c должен иметь одинаковую длину как с массивом b, так и с массивом a, и существует вероятность, что два элемента в массиве a или массиве b совпадают,Массив c также должен состоять из тех же элементов, что и в a и b (т.е. он ведет себя как случайный случай).

Я пробовал несколько решений, но ни одно из них не дает желаемогорезультат.Наиболее близким было следующее:

a = np.arange(10).reshape(5, 2)
np.random.shuffle(a)

b = np.arange(10).reshape(5, 2)
b_part = b[:4]

temp = []

for part in a:
    if part in b_part:
        continue
    else:
        temp.append(part)

temp = np.array(temp)

c = copy.deepcopy(np.vstack((b_part, temp)))

Однако иногда это приводит к тому, что массив c меньше массивов a и b, поскольку элементы в любом списке могут иногда повторяться.

Ответы [ 4 ]

2 голосов
/ 30 марта 2019

Следующее должно хорошо обрабатывать дубликаты.

def mix(a, b, i):                                             
    sa, sb = map(np.lexsort, (a.T, b.T))                      
    mb = np.empty(len(a), '?')                                
    mb[sb] = np.arange(2, dtype='?').repeat((i, len(a)-i))[sa]
    return np.concatenate([a[:i], b[mb]], 0)                             

Это

  • косвенно сортирует a, а b
  • создает маску, которая является Истинойв позициях, не взятых из a, то есть имеет i False и затем len(a)-i Trues.
  • использует порядки сортировки для сопоставления этой маски с b
  • filters b с маской и добавляет к a[:i]

Пример (транспонирован для экономии места):

a.T
# array([[2, 2, 0, 2, 3, 0, 2, 0, 0, 1],
#        [0, 1, 2, 0, 1, 0, 3, 0, 0, 0]])
b.T
# array([[0, 0, 2, 1, 0, 0, 2, 2, 2, 3],
#        [0, 0, 0, 0, 2, 0, 1, 3, 0, 1]])
mix(a, b, 6).T
# array([[2, 2, 0, 2, 3, 0, 0, 1, 0, 2],
#        [0, 1, 2, 0, 1, 0, 0, 0, 0, 3]])
2 голосов
/ 30 марта 2019

Вот одно из решений:

full_len = len(a)

b_not_in_a_part = ~np.all(np.isin(b,a[:i+1]),axis=1)         # Get boolean mask, to apply on b
b_part_len = full_len-i-1                                    # Length of b part of c

c = np.concatenate((a[:i+1], b[b_not_in_a_part,:]), axis=0)  # Contruct c, using the mask for the b part.

Тестирование:

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

i = 2

print ("a is:\n", a)
print ("b is:\n", b)

full_len = len(a)

b_not_in_a_part = ~np.all(np.isin(b,a[:i+1]),axis=1)         # Get boolean mask, to apply on b
b_part_len = full_len-i-1                                    # Length of b part of c

c = np.concatenate((a[:i+1], b[b_not_in_a_part,:]), axis=0)  # Contruct c, using the mask for the b part.
print ("c is:\n", c)

Выход:

a is:
 [[0 1]
 [2 3]
 [0 0]
 [2 3]
 [4 5]
 [6 7]]
b is:
 [[2 3]
 [6 7]
 [0 1]
 [4 5]
 [2 3]
 [0 0]]
c is:
 [[0 1]
 [2 3]
 [0 0]
 [6 7]
 [4 5]]

Примечание: Для этого примера c имеет длину всего 5, хотя a и b имеют длину 6. Это связано с тем, что из-за высокого дублирования в b в b осталось недостаточно значений, которые можно использовать для c.

0 голосов
/ 30 марта 2019
  1. Для i=2 получите первую часть результата:

    c = a[i:]
    
  2. Получите "необычные" элементы между b и c:

    diff = np.array([x for x in b if x not in c])
    
  3. Выберите random элементов из diff и concatenate в исходном массиве:

    s = len(a) - i
    np.concatenate([c, diff[np.random.choice(diff.shape[0], size=s, replace=False), :]], axis=0)
    

ВЫХОД:

array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
0 голосов
/ 30 марта 2019

Просто используйте numpy.concatenate () и убедитесь, что ваш индекс сам по себе плюс 1 (поскольку индексирование numpy идет вверх, но не включает указанное значение индекса, см. Ниже): (Редактировать: похоже, что выизменил массивы a, b и c, поэтому я изменю свой код ниже, чтобы вместить его)

import numpy as np

a = np.array(
[[0, 1],
 [2, 3],
 [4, 5],
 [6, 7]])

b = np.array(
[[2, 3],
 [6, 7],
 [0, 1],
 [4, 5]])


i = 2
c = a[0:i]
for k in b:
    if k not in c:
        c = np.concatenate((c, [k]))

print(c)

Вывод:

[[0 1]
 [2 3]
 [6 7]
 [4 5]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...