Быстрая замена значений в массиве numpy

У меня есть очень большой массив numpy (содержащий до миллиона элементов) как тот ниже:

[ 0  1  6  5  1  2  7  6  2  3  8  7  3  4  9  8  5  6 11 10  6  7 12 11  7
  8 13 12  8  9 14 13 10 11 16 15 11 12 17 16 12 13 18 17 13 14 19 18 15 16
 21 20 16 17 22 21 17 18 23 22 18 19 24 23]

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

{4: 0, 9: 5, 14: 10, 19: 15, 20: 0, 21: 1, 22: 2, 23: 3, 24: 0}

Я хотел бы заменить некоторые элементы согласно карте выше. Массив numpy является действительно большим, и только небольшое подмножество элементов (происходящий как ключи в словаре) будет заменено соответствующими значениями. Что самый быстрый путь состоит в том, чтобы сделать это?

42
задан dzhelil 4 August 2010 в 08:59
поделиться

4 ответа

Я считаю, что есть еще более эффективный метод, но пока попробуйте

from numpy import copy

newArray = copy(theArray)
for k, v in d.iteritems(): newArray[theArray==k] = v

Microbenchmark и проверьте правильность:

#!/usr/bin/env python2.7

from numpy import copy, random, arange

random.seed(0)
data = random.randint(30, size=10**5)

d = {4: 0, 9: 5, 14: 10, 19: 15, 20: 0, 21: 1, 22: 2, 23: 3, 24: 0}
dk = d.keys()
dv = d.values()

def f1(a, d):
    b = copy(a)
    for k, v in d.iteritems():
        b[a==k] = v
    return b

def f2(a, d):
    for i in xrange(len(a)):
        a[i] = d.get(a[i], a[i])
    return a

def f3(a, dk, dv):
    mp = arange(0, max(a)+1)
    mp[dk] = dv
    return mp[a]


a = copy(data)
res = f2(a, d)

assert (f1(data, d) == res).all()
assert (f3(data, dk, dv) == res).all()

Результат:

$ python2.7 -m timeit -s 'from w import f1,f3,data,d,dk,dv' 'f1(data,d)'
100 loops, best of 3: 6.15 msec per loop

$ python2.7 -m timeit -s 'from w import f1,f3,data,d,dk,dv' 'f3(data,dk,dv)'
100 loops, best of 3: 19.6 msec per loop
35
ответ дан 26 November 2019 в 23:47
поделиться

Предполагая, что значения находятся в диапазоне от 0 до некоторого максимального целого числа, можно реализовать быструю замену, используя массив numpy как int-> int dict, как показано ниже

mp = numpy.arange(0,max(data)+1)
mp[replace.keys()] = replace.values()
data = mp[data]

, где сначала

data = [ 0  1  6  5  1  2  7  6  2  3  8  7  3  4  9  8  5  6 11 10  6  7 12 11  7
  8 13 12  8  9 14 13 10 11 16 15 11 12 17 16 12 13 18 17 13 14 19 18 15 16
 21 20 16 17 22 21 17 18 23 22 18 19 24 23]

и заменяясь на

replace = {4: 0, 9: 5, 14: 10, 19: 15, 20: 0, 21: 1, 22: 2, 23: 3, 24: 0}

, мы получаем

data = [ 0  1  6  5  1  2  7  6  2  3  8  7  3  0  5  8  5  6 11 10  6  7 12 11  7
  8 13 12  8  5 10 13 10 11 16 15 11 12 17 16 12 13 18 17 13 10 15 18 15 16
  1  0 16 17  2  1 17 18  3  2 18 15  0  3]
18
ответ дан 26 November 2019 в 23:47
поделиться
for i in xrange(len(the_array)):
    the_array[i] = the_dict.get(the_array[i], the_array[i])
0
ответ дан 26 November 2019 в 23:47
поделиться

Что ж, вам нужно сделать один проход через массив и для каждого элемента заменить его, если он есть в словаре.

for i in xrange( len( theArray ) ):
    if foo[ i ] in dict:
        foo[ i ] = dict[ foo[ i ] ]
0
ответ дан 26 November 2019 в 23:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: