Одновременно изменять вхождения в массиве NumPy - PullRequest
0 голосов
/ 14 июня 2019

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

h = array([string1 1
       string2 1
       string3 1
       string4 3
       string5 4
       string6 2
       string7 2
       string8 4
       string9 3
       string0 2 ])

Во втором столбце я хотел бы изменить все вхождения от 1 до 3, все вхождения от 3 до 2, все вхождения4 к 1

Очевидно, что если я систематически пытаюсь сделать это на месте, я получу ошибку, потому что:

h[,:1 == 1] = 3
h[,:1 == 3] = 2

изменит все 1 на 2

матрица может иметь длину до 50 000 элементов, а значения, которые нужно изменить, могут варьироваться

Я смотрел на похожий вопрос здесь , но он превращал все цифры в 0, и ответы быликонкретно к этому.

Есть ли способ одновременно изменить все эти случаи или мне придется искать другой путь?

Ответы [ 3 ]

2 голосов
/ 14 июня 2019

Вы можете использовать справочную таблицу и расширенную индексацию:

A = np.rec.fromarrays([np.array("The quick brown fox jumps over the lazy dog .".split()), np.array([1,1,1,3,4,2,2,4,3,2])])
A
# rec.array([('The', 1), ('quick', 1), ('brown', 1), ('fox', 3),
#            ('jumps', 4), ('over', 2), ('the', 2), ('lazy', 4), ('dog', 3),
#            ('.', 2)],
#           dtype=[('f0', '<U5'), ('f1', '<i8')])
LU = np.arange(A['f1'].max()+1)
LU[[1,3,4]] = 3,2,1
A['f1'] = LU[A['f1']]
A
# rec.array([('The', 3), ('quick', 3), ('brown', 3), ('fox', 2),
#            ('jumps', 1), ('over', 2), ('the', 2), ('lazy', 1), ('dog', 2),
#            ('.', 2)],
#           dtype=[('f0', '<U5'), ('f1', '<i8')])
1 голос
/ 14 июня 2019

Вы можете либо использовать map напрямую, либо использовать более эффективный numpy.vectorize, чтобы превратить функцию отображения в функцию, которую можно напрямую применить к массиву:

import numpy as np

mapping = {
    1: 3,
    3: 4,
    4: 1
}

a = np.array([1, 2, 3, 4, 5, 1, 2, 3, 4, 5])
mapping_func = np.vectorize(lambda x: mapping[x] if x in mapping else x)
b = mapping_func(a)

print(a)
print(b)

Результат:

[1 2 3 4 5 1 2 3 4 5]
[3 2 4 1 5 3 2 4 1 5]

Обратите внимание, что вам не нужно использовать функцию dict или lambda. Вы можете использовать любую обычную функцию, которая принимает тип данных вашего исходного массива в качестве входных данных (int в данном случае) и возвращает тип данных целевого массива.

1 голос
/ 14 июня 2019

Лучший способ сделать это - использовать dict для отображения значения. Для этого необходимо использовать векторизованную функцию:

import numpy as np
a = [[1,1],[1,2],[1,3]]
a = np.array([[1,1],[1,2],[1,3]])
>>> a
array([[1, 1],
       [1, 2],
       [1, 3]])
dic = {3:2,2:3}
vfunc = np.vectorize(lambda x:dic[x] if x in dic else x) 
a[:,1] = vfunc(a[:,1])
>>> a
array([[1, 1],
       [1, 3],
       [1, 2]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...