NUMPY конвертировать массивы категориальных строк в целочисленный массив - PullRequest
12 голосов
/ 03 июля 2010

Я пытаюсь преобразовать строковый массив категориальных переменных в целочисленный массив категориальных переменных.

Пример.

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

Я понимаю, что это можно сделать с помощью цикла, ноЯ думаю, что есть более простой способ.Спасибо.

Ответы [ 7 ]

36 голосов
/ 15 июля 2010

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])

она может использоваться для воссоздания исходного массива из уникальных

>>> b[c]
array(['a', 'b', 'c', 'a', 'b', 'c'], 
      dtype='|S1')
>>> (b[c] == a).all()
True
25 голосов
/ 01 сентября 2015

... лет спустя ....

Для полноты (поскольку это не упоминается в ответах) и личных причин (у меня всегда *1004* есть 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])
17 голосов
/ 10 июля 2010

Одним из способов является использование функции 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.]])
2 голосов
/ 09 мая 2016

Другой подход заключается в использовании 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)
1 голос
/ 03 июля 2010

Ну, это хак ... но помогает ли это?

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'))
0 голосов
/ 20 января 2019

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

>>> 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)
0 голосов
/ 21 сентября 2017

... проходит еще несколько лет ...

Подумал, я бы предоставил чистое решение на 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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...