2 votes

Calcul de la moyenne pour des groupes 2x2 lignes-colonnes pour un DataFrame

J'ai un DataFrame pour lequel j'aimerais prendre plusieurs moyens et produire une seule série/DataFrame.

J'aimerais que chaque moyenne soit groupée par une 2x2 tranches de l'ensemble du DataFrame.

Un exemple de ceci serait :

df = pd.DataFrame({'0' : [4, 5, 6, 7, 8, 10], '1' : [2, 0, 1, 2, 3, 4],
                   '2' : [2, 4, 6, 8, 10, 12]}).T

df_mean

2.75
3
4
5
.
.
5.75
7.25

La façon dont il serait regroupé serait en prenant la première rangée 2x2 "tranche". ([4, 5], [2, 0]) calculer la moyenne (4+5+2+0)/4 = 2.75 puis répétez cette opération pour chaque tranche jusqu'à la rangée suivante, jusqu'à ce que toutes les tranches 2x2 possibles aient été calculées sur toutes les rangées.

Ie :

([5, 6], [0, 1]).mean() = 3
([6, 7], [1, 2]).mean() = 4
.
.
.
([3, 4], [10, 12]).mean() = 7.25

Je n'arrive qu'à comprendre comment regrouper 2 lignes en bas et prendre la moyenne :

df_mean = df.groupby(np.arange(len(df)) // 2).mean()

Mais cela ne fait que regrouper par 2 dans chaque colonne plutôt que dans une "cellule" 2x2.

Y a-t-il un moyen d'utiliser le groupby pour faire cela ? J'essaie d'éviter les boucles for coûteuses en calcul sur les indices de ligne et de colonne si possible.

4voto

ndclt Points 1737

J'utilise rolling , mean y dropna le long des deux axes afin d'obtenir le résultat souhaité :

import pandas as pd

df = pd.DataFrame(
    {'0': [4, 5, 6, 7, 8, 10], '1': [2, 0, 1, 2, 3, 4], '2': [2, 4, 6, 8, 10, 12]}
).T
mean_df = (
    df.rolling(2)
    .mean()
    .dropna(how='all')
    .rolling(2, axis='columns')
    .mean()
    .dropna(how='all', axis='columns')
)
print(mean_df)

      1     2     3     4     5
1  2.75  3.00  4.00  5.00  6.25
2  2.00  2.75  4.25  5.75  7.25

Rolling crée les Windows sur lesquelles la moyenne est calculée, dropna supprime les lignes où il y a des NaN lorsque la fenêtre prend des valeurs en dehors du cadre de données.

1voto

Quang Hoang Points 191

Si toutes vos données sont du même type, vous pouvez utiliser as_strided :

size = (2,2)

from numpy.lib.stride_tricks import as_strided

strides = df.values.strides

new_rows = (df.shape[0] - size[0] + 1) 
new_cols = (df.shape[1] - size[1] + 1)

array = as_strided(df.values, 
                   (size[0],size[1], new_rows, new_cols), 
                   [strides[0], strides[1], strides[0], strides[1]])

np.mean(array,
        axis=(0,1))

Sortie :

array([[2.75, 3.  , 4.  , 5.  , 6.25],
   [2.  , 2.75, 4.25, 5.75, 7.25]])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X