2015-03-28 5 views
4

У меня есть 1000 * 1000 Numpy массив с 1 миллиона значений, которые были созданы следующим образом:Заменить значения в Numpy массива значениями из другого Numpy массива

>>import numpy as np 
>>data = np.loadtxt('space_data.txt') 
>> print (data) 
>>[[ 13. 15. 15. ..., 15. 15. 16.] 
    [ 14. 13. 14. ..., 13. 15. 16.] 
    [ 16. 13. 13. ..., 13. 15. 17.] 
    ..., 
    [ 14. 15. 14. ..., 14. 14. 13.] 
    [ 15. 15. 16. ..., 16. 15. 14.] 
    [ 14. 13. 16. ..., 16. 16. 16.]] 

У меня есть другой Numpy массив, который имеет 2 колонки следующим образом:

>> print(key) 
>>[[ 10., S], 
    [ 11., S], 
    [ 12., S], 
    [ 13., M], 
    [ 14., L], 
    [ 15., S], 
    [ 16., S], 
    ..., 
    [ 92., XL], 
    [ 93., M], 
    [ 94., XL], 
    [ 95., S]] 

что я бы в основном хочу, чтобы заменить каждый элемент массива данных с соответствующим элементом во втором столбце массива ключей, как это ..

>> print(data) 
>>[[ M S S ..., S S S] 
    [ L M L ..., M S S] 
    [ S M M ..., M S XL] 
    ..., 
    [ L S L ..., L L M] 
    [ S S S ..., S S L] 
    [ L M S ..., S S S]] 
+0

Пожалуйста, исправьте фрагмент кода для 'data', так как это неправильно (пропуски). Это может запутать других пользователей типа данных. – ha9u63ar

+1

S, M, L ... имена переменных или строки? –

+0

они являются строками .. – Amistad

ответ

5

В dicts Python является естественным выбором для отображения от ключей до значений. NumPy имеет никакого прямого эквивалента dict. Но у него есть массивы, которые могут выполнять быстрое целочисленное индексирование. Например,

In [153]: keyarray = np.array(['S','M','L','XL']) 

In [158]: data = np.array([[0,2,1], [1,3,2]]) 

In [159]: keyarray[data] 
Out[159]: 
array([['S', 'L', 'M'], 
     ['M', 'XL', 'L']], 
     dtype='|S2') 

Так что, если мы могли бы помассировать key массив в один, который выглядит следующим образом:

In [161]: keyarray 
Out[161]: 
array(['', '', '', '', '', '', '', '', '', '', 'S', 'S', 'S', 'M', 'L', 
     'S', 'S', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 
     '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 
     '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 
     '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 
     '', '', '', '', '', '', '', '', '', '', 'XL', 'M', 'XL', 'S'], 
     dtype='|S32') 

Так что 10 карт на «S» в том смысле, что keyarray[10] равно S, и так :

In [162]: keyarray[10] 
Out[162]: 'S' 

Тогда мы сможем получить желаемый результат с keyarray[data].


import numpy as np 

data = np.array([[ 13., 15., 15., 15., 15., 16.], 
        [ 14., 13., 14., 13., 15., 16.], 
        [ 16., 13., 13., 13., 15., 17.], 
        [ 14., 15., 14., 14., 14., 13.], 
        [ 15., 15 , 16., 16., 15., 14.], 
        [ 14., 13., 16., 16., 16., 16.]]) 

key = np.array([[ 10., 'S'], 
       [ 11., 'S'], 
       [ 12., 'S'], 
       [ 13., 'M'], 
       [ 14., 'L'], 
       [ 15., 'S'], 
       [ 16., 'S'], 
       [ 17., 'XL'], 
       [ 92., 'XL'], 
       [ 93., 'M'], 
       [ 94., 'XL'], 
       [ 95., 'S']]) 

idx = np.array(key[:,0], dtype=float).astype(int) 
n = idx.max()+1 
keyarray = np.empty(n, dtype=key[:,1].dtype) 
keyarray[:] = '' 
keyarray[idx] = key[:,1] 

data = data.astype('int') 
print(keyarray[data]) 

дает

[['M' 'S' 'S' 'S' 'S' 'S'] 
['L' 'M' 'L' 'M' 'S' 'S'] 
['S' 'M' 'M' 'M' 'S' 'XL'] 
['L' 'S' 'L' 'L' 'L' 'M'] 
['S' 'S' 'S' 'S' 'S' 'L'] 
['L' 'M' 'S' 'S' 'S' 'S']] 

Обратите внимание, что data = data.astype('int') при условии, что поплавки в data может быть однозначно отображается в int с. Это похоже на ваши данные, но это неверно для произвольных поплавков. Например, astype('int') отображает как 1.0, так и 1.5 на 1.

In [167]: np.array([1.0, 1.5]).astype('int') 
Out[167]: array([1, 1]) 
+0

Это фантастика! Большое вам спасибо, это именно то, что я искал. Существует множество реализаций, в которых используются «для» циклов, но это действительно беспристрастно. –

3

маркированного Векторизованный линейный подход будет использовать словарь здесь:

dct = dict(keys) 
# new array is required if dtype is different or it it cannot be casted 
new_array = np.empty(data.shape, dtype=str) 
for index in np.arange(data.size): 
    index = np.unravel_index(index, data.shape) 
    new_array[index] = dct[data[index]] 
1
import numpy as np 

data = np.array([[ 13., 15., 15.], 
    [ 14., 13., 14. ], 
    [ 16., 13., 13. ]]) 

key = [[ 10., 'S'], 
    [ 11., 'S'], 
    [ 12., 'S'], 
    [ 13., 'M'], 
    [ 14., 'L'], 
    [ 15., 'S'], 
    [ 16., 'S']] 

data2 = np.zeros(data.shape, dtype=str) 

for k in key: 
    data2[data == k[0]] = k[1] 
+0

Это должно быть достаточно быстро, если количество элементов в массиве 'key' не огромно, но будет квадратичным, если' key''s размер увеличивается. –

+0

действительно, похоже, должно быть 86 записей в ключе, возможно ... в противном случае, вероятно, самый быстрый –

Смежные вопросы