2017-02-20 26 views
6

W pierwszym przypadku używam bardzo prostego DataFrame, aby spróbować użyć pandas.cut() do zliczenia unikatowych wartości w jednej kolumnie w zakresie innej kolumny. Kod działa zgodnie z oczekiwaniami:Dlaczego pandas.cut() zachowuje się inaczej w unikalnym liczeniu w dwóch podobnych przypadkach?

enter image description here

Jednak w poniższym kodzie pandas.cut() liczy się liczba unikatowych wartości niepowołane. Oczekuję, że pierwszy pojemnik (1462320000, 1462406400) będzie miał 5 unikatowych wartości, a inne pojemniki, w tym ostatni pojemnik (1462752000, 1462838400), będą miały 0 unikatowych wartości:

Zamiast tego, jak pokazano w wyniku, kod zwraca 5 unikalne wartości w ostatniej skrzyni (1462752000, 1462838400], podczas gdy 2 podkreślone wartości nie powinny być liczone, bo są poza zasięgiem.

enter image description here

więc może ktoś wyjaśnić dlaczego pandas.cut() zachowuje się tak różne w tych 2 przypadkach? A także byłbym bardzo wdzięczny, gdyby możesz mi również powiedzieć, jak mogę poprawić kod, aby poprawnie policzyć liczbę unikatowych wartości w jednej kolumnie w zakresie wartości innej kolumny.


źródło dodatkowego INFO: (proszę importować pandas i numpy do uruchomienia kodu, moja wersja pandy jest 0.19.2, a używam Pythona 2.7)

Dla gotowy odniesienia, niniejszym po moi DataFrame i kody, aby odtworzyć mój kod:

Przypadek 1:

df = pd.DataFrame({'No': [1,1.5,2,1,3,5,10], 'useragent': ['a', 'c', 'b', 'c', 'b','a','z']}) 
print type(df) 
print df 
df.groupby(pd.cut(df['No'], bins=np.arange(0,4,1))).useragent.nunique() 

Przypadek 2:

print type(df) 
print len(df) 
print df.time.nunique() 
print df.hash.nunique() 
print df[['time','hash']] 
df.groupby(pd.cut(df['time'], bins =np.arange(1462320000,1462924800,86400))).hash.nunique() 

Przypadek 2 Dane za:

time  hash 
1462328401 qo 
1462328401 qQ 
1462838401 q1 
1462328401 q1 
1462328401 qU 
1462328401 qU 
1462328401 qU 
1462328401 qU 
1462328401 qX 
1462838401 qX 

Odpowiedz

2

To wydaje się być bug.

na prostym przykładzie:

In [50]: df=pd.DataFrame({'atime': [28]*8+[38]*2, 'hash':randint(0,3,10)} 
).sort_values('hash') 
Out[50]: 
     atime hash 
1  28  0 
3  28  0 
4  28  0 
5  28  0 
8  38  0 
2  28  1 
6  28  1 
0  28  2 
7  28  2 
9  38  2 

In [50bis;)]: df.groupby(pd.cut(df.atime,bins=arange(27,40,2))).hash.unique() 
Out[50bis]: 
atime 
(27, 29]     [0, 1, 2] # ok 
(29, 31]       [] 
(31, 33]       [] 
(33, 35]       [] 
(35, 37]       [] 
(37, 39]      [0, 2] 
Name: hash, dtype: object 

In [51]: df.groupby(pd.cut(df.atime,bins=arange(27,40,2))).hash.nunique() 
Out[51]: 
atime 
(27, 29] 2 # bug 
(29, 31] 0 
(31, 33] 0 
(33, 35] 0 
(35, 37] 0 
(37, 39] 2 
Name: hash, dtype: int64 

Tutaj wydaje się być skuteczne obejście, przekształcając rezultat cięcia w formie listy:

In [52]: df.groupby(pd.cut(df.atime,bins=arange(27,40,2)).tolist() 
).hash.nunique() 
Out[52]: 
atime 
(27, 29] 3 
(37, 39] 2 
Name: hash, dtype: int64 
+0

działa jak czar. Dziękuję za niespodziankę z tolist() – weefwefwqg3