我正在尝试将分类变量的字符串数组转换为分类变量的整数数组。
实施例
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
我意识到这可以通过循环完成,但我想有一种更简单的方法。感谢。
答案 0 :(得分:36)
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
答案 1 :(得分:24)
......多年后......
为了完整性(因为答案中没有提及)和个人原因(我总是在我的模块中导入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])
答案 2 :(得分:17)
一种方法是使用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.]])
答案 3 :(得分:2)
另一种方法是使用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)
答案 4 :(得分: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'))
答案 5 :(得分:1)
另一种方法是使用sklearn.preprocessing.LabelEncoder
它可以将诸如字符串之类的可哈希标签转换为介于0到n_classes-1
之间的数值。
它是这样完成的:
# Repeating setup from the question to make example copy/paste-able
import numpy as np
a = np.array( ['a', 'b', 'c', 'a', 'b', 'c'])
b = np.unique(a)
# Answer to the question
from sklearn import preprocessing
pre = preprocessing.LabelEncoder()
pre.fit(b)
c = pre.transform(a)
print(c) # Prints [0 1 2 0 1 2]
如果您坚持要让结果数组中的值从1开始,那么您可以在此之后简单地c + 1
。
仅将sklearn作为依赖项引入项目中可能不值得,但是如果您已经导入了sklearn,这是一个不错的选择。
答案 6 :(得分:0)
......再过几年......
以为我会为完整性提供纯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]
答案 7 :(得分:0)
另一种选择是使用大熊猫分类:
>>> 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)
答案 8 :(得分:0)
你也可以试试这样的:
a = np.array( ['a', 'b', 'c', 'a', 'b', 'c'])
a[a == 'a'] = 1
a[a == 'b'] = 2
a[a == 'c'] = 3
a = a.astype(np.float32)
如果你知道里面有什么并且希望为每个值设置特定的索引会更好。
如果只有两个类别,则下一个代码将非常有用:
a = np.array( ['a', 'b', 'a', 'b'])
a = np.float32(y == 'a')