Ответ 1
Ну, это взломать... но помогает ли это?
In [72]: c=(a.view(np.ubyte)-96).astype('int32')
In [73]: print(c,c.dtype)
(array([1, 2, 3, 1, 2, 3]), dtype('int32'))
Я пытаюсь преобразовать массив строк категориальных переменных в целочисленный массив категориальных переменных.
Исх.
import numpy as np
a = np.array( ['a', 'b', 'c', 'a', 'b', 'c'])
print a.dtype
>>> |S1
b = np.unique(a)
print b
>>> ['a' 'b' 'c']
c = a.desired_function(b)
print c, c.dtype
>>> [1,2,3,1,2,3] int32
Я понимаю, что это можно сделать с помощью цикла, но я думаю, что есть более простой способ. Спасибо.
Ну, это взломать... но помогает ли это?
In [72]: c=(a.view(np.ubyte)-96).astype('int32')
In [73]: print(c,c.dtype)
(array([1, 2, 3, 1, 2, 3]), dtype('int32'))
np.unique имеет несколько необязательных возвратов
return_inverse дает целочисленную кодировку, которую я часто использую
>>> b, c = np.unique(a, return_inverse=True)
>>> b
array(['a', 'b', 'c'],
dtype='|S1')
>>> c
array([0, 1, 2, 0, 1, 2])
>>> c+1
array([1, 2, 3, 1, 2, 3])
его можно использовать для воссоздания исходного массива из uniques
>>> b[c]
array(['a', 'b', 'c', 'a', 'b', 'c'],
dtype='|S1')
>>> (b[c] == a).all()
True
... спустя годы....
Для полноты (потому что это не упоминается в ответах) и личных причин (у меня всегда есть pandas
, импортированных в мои модули, но не обязательно sklearn
), это также довольно просто с pandas.get_dummies()
import numpy as np
import pandas
In [1]: a = np.array(['a', 'b', 'c', 'a', 'b', 'c'])
In [2]: b = pandas.get_dummies(a)
In [3]: b
Out[3]:
a b c
0 1 0 0
1 0 1 0
2 0 0 1
3 1 0 0
4 0 1 0
5 0 0 1
In [3]: b.values.argmax(1)
Out[4]: array([0, 1, 2, 0, 1, 2])
Один из способов - использовать categorical
функцию из scikits. statsmodels. Например:
In [60]: from scikits.statsmodels.tools import categorical
In [61]: a = np.array( ['a', 'b', 'c', 'a', 'b', 'c'])
In [62]: b = categorical(a, drop=True)
In [63]: b.argmax(1)
Out[63]: array([0, 1, 2, 0, 1, 2])
Возвращаемое значение categorical
(b
) на самом деле является матрицей дизайна, поэтому вызов argmax
выше, чтобы приблизить его к вашему желаемому формату.
In [64]: b
Out[64]:
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.],
[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
Другим подходом является использование Pandas factorize
для сопоставления элементов с числом:
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: a = np.array(['a', 'b', 'c', 'a', 'b', 'c'])
In [4]: a_enc = pd.factorize(a)
In [5]: a_enc[0]
Out[5]: array([0, 1, 2, 0, 1, 2])
In [6]: a_enc[1]
Out[6]: array(['a', 'b', 'c'], dtype=object)
... еще несколько лет проходят...
Думаю, я бы предоставил чистое решение python для полноты:
def count_unique(a):
def counter(item, c=[0], items={}):
if item not in items:
items[item] = c[0]
c[0] += 1
return items[item]
return map(counter, a)
a = [0, 2, 6, 0, 2]
print count_unique(a)
>> [0, 1, 2, 0, 1]
Другим вариантом является использование категориальных панд серии:
>>> import pandas as pd
>>> pd.Series(['a', 'b', 'c', 'a', 'b', 'c'], dtype="category").cat.codes.values
array([0, 1, 2, 0, 1, 2], dtype=int8)