2016-05-07 93 views
5

我想爲給定的2d數據集製作2d直方圖(或其他統計數據,但讓我們以直方圖爲例)。問題是空箱看起來完全被丟棄。例如,pandas groupby報告空箱

import numpy 
import pandas 

numpy.random.seed(35) 
values = numpy.random.random((2,10000)) 

xbins = numpy.linspace(0, 1.2, 7) 
ybins = numpy.linspace(0, 1, 6) 

我可以輕鬆地獲得所需的輸出與

print numpy.histogram2d(values[0], values[1], (xbins,ybins)) 

[[ 408. 373. 405. 411. 400.] 
[ 390. 413. 400. 414. 368.] 
[ 354. 414. 421. 400. 413.] 
[ 426. 393. 407. 416. 412.] 
[ 412. 397. 396. 356. 401.] 
[ 0. 0. 0. 0. 0.]] 

然而,與大熊貓,

df = pandas.DataFrame({'x': values[0], 'y': values[1]}) 
binned = df.groupby([pandas.cut(df['x'], xbins), 
        pandas.cut(df['y'], ybins)]) 
print binned.size().unstack() 

打印

y   (0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1] 
x                 
(0, 0.2]   408   373   405   411  400 
(0.2, 0.4]  390   413   400   414  368 
(0.4, 0.6]  354   414   421   400  413 
(0.6, 0.8]  426   393   407   416  412 
(0.8, 1]   412   397   396   356  401 

即最後一行1 < x <= 1.2完全缺失,因爲它裏面沒有任何值。不過,我想明確地看到(如使用numpy.histogram2d時)。在這個例子中,我可以使用numpy很好,但在更復雜的設置(n維binning,或計算統計以外的統計等),pandas可以更有效的編碼和計算比numpy

原則上,我可以想出各種辦法來檢查,如果索引存在,使用類似

allkeys = [('({0}, {1}]'.format(xbins[i-1], xbins[i]), 
      '({0}, {1}]'.format(ybins[j-1], ybins[j])) 
      for j in xrange(1, len(ybins)) 
      for i in xrange(1, len(xbins))] 

然而,問題是索引格式並不一致,在這個意義上,你見上面,binned的第一個索引是['(0, 0.2]', '(0, 0.2]'],但allkeys的第一個條目是['(0.0, 0.2]', '(0.0, 0.2]'],所以我不能匹配allkeysbinned.viewkeys()

任何幫助,非常感謝。

+1

看起來像'.size()'忽略遺漏值。解決方法是使用'count()',在這種情況下應用於'binned' groupby對象時,似乎保留缺失的值:'binned.count()['x']。unstack()。fillna(0 )'。 –

+1

似乎這個行爲可能在'pandas'' v0.16'(可在我的工作計算機中)後發生改變。如果我運行'binned.count()'我得到'ValueError:無法將NA轉換爲整數'。然而,在我的筆記本電腦中(使用'v0.17.1')'count()'可以正常工作。 –

+2

這是一個猜測,但如果你做'binned.agg(lambda x:1.0 * x.count())。unstack()'會發生什麼?它應該返回花車,所以希望nan不會被轉換。 – ptrj

回答

0

看來,pd.cut保持,這意味着我們可以在一個reindex使用您的信息分級:

In [79]: xcut = pd.cut(df['x'], xbins) 

In [80]: ycut = pd.cut(df['y'], ybins) 

In [81]: binned = df.groupby([xcut, ycut]) 

In [82]: sizes = binned.size() 

In [85]: (sizes.reindex(pd.MultiIndex.from_product([xcut.cat.categories, ycut.cat.categories])) 
    ...:  .unstack() 
    ...:  .fillna(0.0)) 
    ...: 
Out[85]: 
      (0.0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1.0] 
(0.0, 0.2]  408.0  373.0  405.0  411.0  400.0 
(0.2, 0.4]  390.0  413.0  400.0  414.0  368.0 
(0.4, 0.6]  354.0  414.0  421.0  400.0  413.0 
(0.6, 0.8]  426.0  393.0  407.0  416.0  412.0 
(0.8, 1.0]  412.0  397.0  396.0  356.0  401.0 
(1.0, 1.2]   0.0   0.0   0.0   0.0   0.0