Comment effectuer une opération fenêtrée sur dataframe?

Oct 27 2020

Donné

import pandas as pd
import numpy as np

ssss = pd.DataFrame(np.arange(6))

ssss:

   0
0  0
1  1
2  2
3  3
4  4
5  5

Je souhaite effectuer une opération de fenêtre glissante sur le dataframe.

Je veux effectuer une fonction générale (dans ce cas, cela signifie, mais cela peut être une autre fonction et impliquer plus d'une colonne d'entrée), sur une fenêtre glissante de taille arbitraire, avec des enjambées arbitraires.

Dans ce cas, la taille de la fenêtre est de 2 et la longueur de foulée est également de 2.

Les pandas supportent-ils ce genre d'opération?

res:

   0 res
0  0 0.5
1  1 0.5
2  2 2.5
3  3 2.5
4  4 4.5
5  5 4.5

Il semble que groupbyce ne soit pas ce que je recherche.

Je pourrais aller à une solution stupide, mais même dans ce cas, je ne suis pas sûr de l'approche standard. Je m'attendrais à ce que les pandas soutiennent quelque chose comme ça, mais je n'ai trouvé aucune méthode qui fasse cela.


Éditer:

ssss:

Supposons que les valeurs de la colonne 1 sont des chaînes

   0 1   2
0  0 "5" a
1  1 "4" b
2  2 "3" c
3  3 "2" d
4  4 "1" e
5  5 "0" f

Je voudrais utiliser comme exemple très général

def row_reduce(col0, col1):
    return str(2 * col0) + col1

def col_reduce(rows_data):
    return ",".join(rows_data)

pour obtenir (en ignorant la colonne 2)

   0 1   2 res
0  0 "5" a "05,24"
1  1 "4" b "05,24"
2  2 "3" c "43,62"
3  3 "2" d "43,62"
4  4 "1" e "81,100"
5  5 "0" f "81,100"

Ceci effectue d'abord la réduction de ligne à l'aide de la fonction personnalisée, puis effectue une réduction de colonne fenêtrée.

Réponses

2 jezrael Oct 27 2020 at 11:55

Si les fenêtres ne se chevauchent pas, vous pouvez utiliser groupby.

Je pense que vous avez besoin GroupBy.transformd'une division entière:

#if default RangeIndex
ssss['res'] = ssss.groupby(ssss.index // 2)[0].transform('mean')
#any index - helper array
ssss['res'] = ssss.groupby(np.arange(len(ssss)) // 2)[0].transform('mean')
print (ssss)
   0  res
0  0  0.5
1  1  0.5
2  2  2.5
3  3  2.5
4  4  4.5
5  5  4.5

ÉDITER:

print (df)
   0  1  2
0  0  5  a
1  1  4  b
2  2  3  c
3  3  2  d
4  4  1  e
5  5  0  f

def row_reduce(col0, col1):
    return str(2 * col0) + str(col1)

def col_reduce(rows_data):
    return ",".join(rows_data)


df['res'] = (df.apply(lambda x: row_reduce(x[0], x[1]), axis=1)
               .groupby(df.index // 2)
               .transform(col_reduce))
print (df)
   0  1  2     res
0  0  5  a   05,24
1  1  4  b   05,24
2  2  3  c   43,62
3  3  2  d   43,62
4  4  1  e  81,100
5  5  0  f  81,100