2016-05-07 36 views
5

Voglio creare un istogramma 2d (o altre statistiche, ma prendiamo un istogramma per l'esempio) di un dato set di dati 2d. Il problema è che i contenitori vuoti sembrano essere scartati del tutto. Per esempio,pandas groupby report bidoni vuoti

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) 

mi può facilmente ottenere l'output desiderato con

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

dando

[[ 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.]] 

Tuttavia, con i panda,

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() 

stampe

0.123.516,410617 millions
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 

Ad esempio, l'ultima riga, con 1 < x <= 1.2, manca completamente, perché non ci sono valori in essa. Tuttavia mi piacerebbe vederlo esplicitamente (come quando si usa numpy.histogram2d). In questo esempio posso usare numpy bene ma su impostazioni più complicate (binning bidimensionale, calcolo di statistiche diverse dai conteggi, ecc.), pandas può essere più efficiente codificare e calcolare che numpy.

In linea di principio posso trovare dei modi per verificare se un indice è presente, usando qualcosa come

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))] 

Tuttavia, il problema è che la formattazione dell'indice non è coerente, nel senso che, come si vedi sopra, il primo indice di binned è ['(0, 0.2]', '(0, 0.2]'] ma la prima voce in allkeys è ['(0.0, 0.2]', '(0.0, 0.2]'], quindi non posso corrispondere a allkeys a binned.viewkeys().

Qualsiasi aiuto è molto apprezzato.

+1

Sembra '.size()' ignora i valori mancanti. Una soluzione alternativa potrebbe essere usare 'count()' che sembra mantenere i valori mancanti quando applicati all'oggetto groupby 'binned' in questo caso:' binned.count() ['x']. Unstack(). Fillna (0) '. –

+1

Sembra che il comportamento possa essere cambiato dopo 'pandas'' v0.16' (disponibile nel mio computer di lavoro). Se eseguo 'binned.count()' Ottengo 'ValueError: Can not Convertire NA to integer'. Comunque nel mio laptop (con 'v0.17.1')' count() 'funziona bene. –

+2

È un'ipotesi, ma cosa succede se esegui 'binned.agg (lambda x: 1.0 * x.count()). Unstack()'? Dovrebbe restituire i float, quindi si spera che i nan non vengano convertiti. – ptrj

risposta

0

Sembra che pd.cut mantiene le informazioni di binning che significa che possiamo utilizzare in un 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 
Problemi correlati