2011-10-18 14 views
10

Próbuję zrobić coś bardzo podobnego do tego previous question, ale napotkałem błąd. Mam dataframe pandy zawierającego funkcje i etykietę muszę zrobić konwersja do wysyłania cechy i zmienną etykiety do obiektu uczenia maszynowego:Konwertuj tablicę ciągu (kategorię) na tablicę int z pandasowej ramki danych

import pandas 
import milk 
from scikits.statsmodels.tools import categorical 

potem mam:

trainedData=bigdata[bigdata['meta']<15] 
untrained=bigdata[bigdata['meta']>=15] 
#print trainedData 
#extract two columns from trainedData 
#convert to numpy array 
features=trainedData.ix[:,['ratio','area']].as_matrix(['ratio','area']) 
un_features=untrained.ix[:,['ratio','area']].as_matrix(['ratio','area']) 
print 'features' 
print features[:5] 
##label is a string:single, touching,nuclei,dust 
print 'labels' 

labels=trainedData.ix[:,['type']].as_matrix(['type']) 
print labels[:5] 
#convert single to 0, touching to 1, nuclei to 2, dusts to 3 
# 
tmp=categorical(labels,drop=True) 
targets=categorical(labels,drop=True).argmax(1) 
print targets 

Wyjście konsola daje pierwszy:

features 
[[ 0.38846334 0.97681855] 
[ 3.8318634 0.5724734 ] 
[ 0.67710876 1.01816444] 
[ 1.12024943 0.91508699] 
[ 7.51749674 1.00156707]] 
labels 
[[single] 
[touching] 
[single] 
[single] 
[nuclei]] 

spotkam wtedy następujący błąd:

Traceback (most recent call last): 
File "/home/claire/Applications/ProjetPython/projet particule et objet/karyotyper/DAPI-Trainer02-MILK.py", line 83, in <module> 
tmp=categorical(labels,drop=True) 
File "/usr/local/lib/python2.6/dist-packages/scikits.statsmodels-0.3.0rc1-py2.6.egg/scikits/statsmodels/tools/tools.py", line 206, in categorical 
tmp_dummy = (tmp_arr[:,None]==data).astype(float) 
AttributeError: 'bool' object has no attribute 'astype' 

Czy można przekonwertować zmienną kategorii "type" w ramce danych na int? "type" może przyjmować wartości "pojedyncze", "dotykające", "jądra", "pyły" i muszę konwertować z wartościami int, takimi jak 0, 1, 2, 3.

Odpowiedz

10

Jeśli masz wektor ciągów znaków lub inne przedmioty i chcesz nadać mu kategoryczne etykiet, można użyć klasy Factor (dostępne w przestrzeni nazw pandas):

In [1]: s = Series(['single', 'touching', 'nuclei', 'dusts', 'touching', 'single', 'nuclei']) 

In [2]: s 
Out[2]: 
0 single 
1 touching 
2 nuclei 
3 dusts 
4 touching 
5 single 
6 nuclei 
Name: None, Length: 7 

In [4]: Factor(s) 
Out[4]: 
Factor: 
array([single, touching, nuclei, dusts, touching, single, nuclei], dtype=object) 
Levels (4): [dusts nuclei single touching] 

czynnik ma atrybuty labels i levels:

In [7]: f = Factor(s) 

In [8]: f.labels 
Out[8]: array([2, 3, 1, 0, 3, 2, 1], dtype=int32) 

In [9]: f.levels 
Out[9]: Index([dusts, nuclei, single, touching], dtype=object) 

To jest przeznaczone dla wektorów 1D o nie wiem, czy można go natychmiast zastosować do problemu, ale spójrz.

BTW Polecam, aby zadać te pytania na liście wysyłkowej statsmodels i/lub scikit-learn, ponieważ większość z nas nie jest częstym użytkownikiem SO.

+4

myślę, że klasa Factor został zmieniony, ponieważ ten post został wykonany. Kiedy próbuję uruchomić opublikowany kod, pojawia się błąd stwierdzający, że czynnik oczekuje 3 argumentów i 2 zostały podane. Patrząc na dokumentację dla Factor, tego oczekuje konstruktor: {{{Factor (self, labels, levels, name = None)}}}. Ze swojego posta założyłem, że etykiety i poziomy zostały automatycznie obliczone z serii, ale wydaje się, że czynnik oczekuje, że zostaną one przekazane do współczynnika. – CadentOrange

+10

Czynnik został przemianowany na kategoryczny w pandach 0.8.0 (6/2012) – smci

6

Odpowiadam na pytanie dotyczące Pand 0.10.1. Factor.from_array wydaje się, że to wystarczy.

>>> s = pandas.Series(['a', 'b', 'a', 'c', 'a', 'b', 'a']) 
>>> s 
0 a 
1 b 
2 a 
3 c 
4 a 
5 b 
6 a 
>>> f = pandas.Factor.from_array(s) 
>>> f 
Categorical: 
array([a, b, a, c, a, b, a], dtype=object) 
Levels (3): Index([a, b, c], dtype=object) 
>>> f.labels 
array([0, 1, 0, 2, 0, 1, 0]) 
>>> f.levels 
Index([a, b, c], dtype=object) 
16

Dotychczasowe odpowiedzi są nieaktualne, więc o to rozwiązanie dla ciągów mapowania numerów, które współpracuje z wersją 0.18.1 pand.

dla serii:

In [1]: import pandas as pd 
In [2]: s = pd.Series(['single', 'touching', 'nuclei', 'dusts', 
         'touching', 'single', 'nuclei']) 
In [3]: s_enc = pd.factorize(s) 
In [4]: s_enc[0] 
Out[4]: array([0, 1, 2, 3, 1, 0, 2]) 
In [5]: s_enc[1] 
Out[5]: Index([u'single', u'touching', u'nuclei', u'dusts'], dtype='object') 

Dla DataFrame:

In [1]: import pandas as pd 
In [2]: df = pd.DataFrame({'labels': ['single', 'touching', 'nuclei', 
         'dusts', 'touching', 'single', 'nuclei']}) 
In [3]: catenc = pd.factorize(df['labels']) 
In [4]: catenc 
Out[4]: (array([0, 1, 2, 3, 1, 0, 2]), 
     Index([u'single', u'touching', u'nuclei', u'dusts'], 
     dtype='object')) 
In [5]: df['labels_enc'] = catenc[0] 
In [6]: df 
Out[4]: 
     labels labels_enc 
    0 single   0 
    1 touching   1 
    2 nuclei   2 
    3  dusts   3 
    4 touching   1 
    5 single   0 
    6 nuclei   2 
Powiązane problemy