2015-07-12 21 views
6

Qual è il modo più efficace per trovare sequenzialmente la media e la mediana delle righe in una lista Python?Calcola efficientemente la media e la mediana

Per esempio, la mia lista:

input_list = [1,2,4,6,7,8] 

Voglio produrre un elenco di output che contiene:

output_list_mean = [1,1.5,2.3,3.25,4,4.7] 
output_list_median = [1,1.5,2.0,3.0,4.0,5.0] 

casi in cui è calcolata la media come segue:

  • 1 = media (1)
  • 1.5 = media (1,2) (cioè media dei primi 2 valori in input_list)
  • 2.3 = media (1,2,4) (ad es. media dei primi 3 valori input_list)
  • 3.25 = medio (1,2,4,6) (cioè significa dei primi 4 valori input_list) ecc

E la mediana è calcolata come segue:

  • 1 = mediana (1)
  • 1,5 = mediana (1,2) (cioè mediana dei primi 2 valori input_list)
  • 2.0 = mediana (1,2,4) (cioè mediano primi 3 valori in input_list)
  • 3.0 = mediana (1,2,4,6) (cioè mediana dei primi 4 valori input_list) ecc

ho cercato di attuare con il seguente ciclo, ma sembra molto inefficiente.

import numpy 

input_list = [1,2,4,6,7,8] 

for item in range(1,len(input_list)+1): 
    print(numpy.mean(input_list[:item])) 
    print(numpy.median(input_list[:item])) 
+0

"sembra molto inefficiente" rispetto a cosa? Hai tempo? Sospetto che 'import numpy' domini il runtime (e non ne hai bisogno) – msw

risposta

4

È possibile utilizzare itertools.islice per tagliare l'array e utilizzare np.fromiter con np.mean:

>>> arr=np.array([1,2,4,6,7,8]) 
>>> l=arr.size 
>>> from itertools import islice 
>>> [np.fromiter(islice(arr,0,i+1),float).mean(dtype=np.float32) for i in xrange(l)] 
[1.0, 1.5, 2.3333333, 3.25, 4.0, 4.6666665] 

Come risposta alternativa se si desidera che la media è possibile utilizzare np.cumsum per ottenere una somma cumulativa del tuo elementi e dividere con la matrice principale utilizzando np.true_divide:

>>> np.true_divide(np.cumsum(arr),arr) 
array([ 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5]) 
+0

Grazie @Kasra! Posso usare np per trovare anche la mediana sequenziale? –

+0

@hoof_hearted Benvenuto! scusa cosa intendi per * mediana sequenziale *? – Kasramvd

+0

Come in, ho bisogno di trovare la mediana del primo valore (1), i primi due valori (1,2), i primi tre valori (1,2,3) ecc. L'output sarebbe lo stesso in questo esempio (ie output_list = [1,1,5,2,2,5,3,3,5,4,4,5]), ma sto calcolando la mediana di tutti i valori, al contrario della media. Spero che sia chiaro –

8

Qualunque la cosa che fai tu stesso, specialmente con la mediana, o richiederà molto lavoro, o sarà molto inefficiente, ma Pandas viene fornito con implementazioni efficienti integrate delle funzioni che stai cercando, la media espandibile è O (n), la mediana espansione è O (n * log (n)) utilizzando una skip list:

import pandas as pd 
import numpy as np 

input_list = [1, 2, 4, 6, 7, 8] 

>>> pd.expanding_mean(np.array(input_list)) 
array([ 1.  , 1.5 , 2.33333, 3.25 , 4.  , 4.66667]) 

>>> pd.expanding_median(np.array(input_list)) 
array([ 1. , 1.5, 2. , 3. , 4. , 5. ]) 
0
import numpy as np 
a = np.array([1,2,4,6,7,8]) 

Usa numpy.meshgrid (ci sono altre formulazioni che lavorano) e numpy.triu per creare un array con i valori che vi interessano in.

x, y = np.meshgrid(a,a) 
# y = a.repeat(len(a)).reshape(len(a), len(a)) 
c = np.triu(y) 

>>> y 
array([[1, 1, 1, 1, 1, 1], 
     [2, 2, 2, 2, 2, 2], 
     [4, 4, 4, 4, 4, 4], 
     [6, 6, 6, 6, 6, 6], 
     [7, 7, 7, 7, 7, 7], 
     [8, 8, 8, 8, 8, 8]]) 
>>> c 
array([[1, 1, 1, 1, 1, 1], 
     [0, 2, 2, 2, 2, 2], 
     [0, 0, 4, 4, 4, 4], 
     [0, 0, 0, 6, 6, 6], 
     [0, 0, 0, 0, 7, 7], 
     [0, 0, 0, 0, 0, 8]]) 

Definire una funzione che restituisce la mediana di tutti i valori diversi da zero e applicala al tuo interessante array.

def foo(a): 
    '''return the the median of the non-zero elements of a 1d array 
    ''' 
    return np.median(a[a.nonzero()]) 
d = np.apply_along_axis(foo, 0, c) 

>>> d 
array([ 1. , 1.5, 2. , 3. , 4. , 5. ]) 
>>> 
Problemi correlati