Implementation

This page describes the internal flow of weighted_mean and the order in which input validation, selection of the unweighted or weighted branch, and final mean calculation are applied. Unlike Overview, the goal here is not to repeat the parameters, but to show how the function actually builds the result.

The following snippets are taken from the current src/mespy/stats_utils.py implementation. Private helpers are mentioned only to clarify the flow; complete details are documented in _as_float_vector and _validate_weights.

Execution sequence

The implementation follows this sequence:

  1. Converts x into a one-dimensional, finite float64 vector.

  2. If w is provided, it validates it as a vector with the same shape as x, strictly positive, and with a finite positive sum.

  3. If w is None, it computes the simple arithmetic mean with np.mean(values).

  4. If w is valid, it computes the weighted mean as the ratio between weighted sum and sum of weights.

  5. Always converts the result to a Python float.

Validation and selection of the numerical branch

def weighted_mean(x: ArrayLike, w: ArrayLike | None = None) -> float:
    values = _as_float_vector("x", x)
    weights = _validate_weights(values, w)

    if weights is None:
        return float(np.mean(values))

    return float(np.sum(values * weights) / np.sum(weights))

The first step is shared across the whole module: values must be a one-dimensional, non-empty numeric vector without NaN values or infinities.

The second step decides whether the function stays in the base case or enters the weighted case.

  • Se w is None, _validate_weights(...) restituisce None e weighted_mean ricade esplicitamente nel ramo non pesato.

  • Se w e presente, _validate_weights(...) impone compatibilita di forma con x, stretta positivita di ogni peso e positivita finita della somma complessiva.

  • In altre parole, weighted_mean non prova mai a “riparare” pesi invalidi: richiede che il vettore sia gia coerente con il significato statistico atteso.

Implemented formula

Nel caso non pesato la funzione usa semplicemente

\[ \bar{x} = \frac{1}{n}\sum_i x_i, \]

tramite np.mean(values).

Nel caso pesato il codice implementa invece

\[ \bar{x}_w = \frac{\sum_i w_i x_i}{\sum_i w_i}. \]

Questo si riflette direttamente nell’ultima riga del frammento:

return float(np.sum(values * weights) / np.sum(weights))
  • Il numeratore somma i contributi x_i moltiplicati per il rispettivo peso.

  • Il denominatore normalizza il risultato usando la somma degli stessi pesi.

  • La funzione non normalizza w in anticipo: usa i pesi cosi come arrivano, purche siano validi.

Important interactions between inputs and the result

A few practical details define the actual behavior of weighted_mean.

  • Pesi uniformi producono lo stesso risultato della media aritmetica semplice, ma il percorso interno resta quello pesato.

  • La funzione accetta qualunque scala positiva dei pesi: moltiplicare tutti i w_i per la stessa costante non cambia il risultato finale.

  • Zeri e valori negativi non sono ammessi, quindi non esiste un ramo in cui alcuni punti vengano “spenti” con peso nullo.

  • La somma dei pesi compare esplicitamente nella formula finale, ma il controllo sulla sua positivita e anticipato in _validate_weights, cosi il calcolo non arriva mai a un denominatore nullo o non finito.