недобросовестные панды категоричны.from_codes

Я должен присвоить категориальным данным метку. Рассмотрим пример радужной оболочки глаза:

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris

iris = load_iris()

print "targets: ", np.unique(iris.target)
print "targets: ", iris.target.shape
print "target_names: ", np.unique(iris.target_names)
print "target_names: ", iris.target_names.shape

Будет напечатано:

цели: [0 1 2] цели: (150L,) target_names: ['setosa' 'versicolor' 'virginica'] target_names: (3L,)

Для создания желаемых этикеток я использую pandas.Categorical.from_codes:

print pd.Categorical.from_codes(iris.target, iris.target_names)

[setosa, setosa, setosa, setosa, setosa, ..., virginica, virginica, virginica, virginica, virginica] Длина: 150 Категории (3, объект): [setosa, versicolor, virginica]

Попробуем это на другом примере:

# I define new targets
target = np.array([123,123,54,123,123,54,2,54,2])
target = np.array([1,1,3,1,1,3,2,3,2])
target_names = np.array(['paglia','gioele','papa'])
#---
print "targets: ", np.unique(target)
print "targets: ", target.shape
print "target_names: ", np.unique(target_names)
print "target_names: ", target_names.shape

Если я снова попытаюсь преобразовать категориальные значения в метках:

print pd.Categorical.from_codes(target, target_names) 

Я получаю сообщение об ошибке:

C: \ Users \ ianni \ Anaconda2 \ lib \ site-packages \ pandas \ core \ategorical.pyc в from_codes (cls, коды, категории, упорядоченные) 459460, если len (коды) и (коды.max ()> = len (категории) или code.min () ‹-1): -> 461 поднять ValueError (« коды должны быть между -1 и «462» len (категории) -1 ») 463

ValueError: коды должны быть от -1 до len (категории) -1

Ты знаешь почему?


person Andrea Ianni ௫    schedule 17.12.2017    source источник


Ответы (1)


Ты знаешь почему?

Если вы внимательно посмотрите на трассировку ошибок:

In [128]: pd.Categorical.from_codes(target, target_names)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-128-c2b4f6ac2369> in <module>()
----> 1 pd.Categorical.from_codes(target, target_names)

~\Anaconda3_5.0\envs\py36\lib\site-packages\pandas\core\categorical.py in from_codes(cls, codes, categories, ordered)
    619
    620         if len(codes) and (codes.max() >= len(categories) or codes.min() < -1):
--> 621             raise ValueError("codes need to be between -1 and "
    622                              "len(categories)-1")
    623

ValueError: codes need to be between -1 and len(categories)-1

вы увидите, что выполняется следующее условие:

codes.max() >= len(categories)

в твоем случае:

In [133]: target.max() >= len(target_names)
Out[133]: True

Другими словами, pd.Categorical.from_codes() ожидает codes как последовательные числа, начиная с 0 до len(categories) - 1.

Временное решение:

In [173]: target
Out[173]: array([123, 123,  54, 123, 123,  54,   2,  54,   2])

помощник диктует:

In [174]: mapping = dict(zip(np.unique(target), np.arange(len(target_names))))

In [175]: mapping
Out[175]: {2: 0, 54: 1, 123: 2}

In [176]: reverse_mapping = {v:k for k,v in mapping.items()}

In [177]: reverse_mapping
Out[177]: {0: 2, 1: 54, 2: 123}

Строительная категориальная серия:

In [178]: ser = pd.Categorical.from_codes(pd.Series(target).map(mapping), target_names)

In [179]: ser
Out[179]:
[papa, papa, gioele, papa, papa, gioele, paglia, gioele, paglia]
Categories (3, object): [paglia, gioele, papa]

обратное отображение:

In [180]: pd.Series(ser.codes).map(reverse_mapping)
Out[180]:
0    123
1    123
2     54
3    123
4    123
5     54
6      2
7     54
8      2
dtype: int64
person MaxU    schedule 17.12.2017