9
votes

Filtrage des pandas ou des tableaux numpus pour une série continue avec une longueur minimale de la fenêtre

Je voudrais filtrer un numpy code> tableau code> (ou pandas code> dataframe code>) de manière continue série de la même valeur avec au moins fenêtre_size code> est conservée et tout le reste réglé sur 0.

Par exemple: P>

import numpy as np
import pandas as pd
import scipy
#from scipy import ndimage
df= pd.DataFrame({'x':np.array([1,1,1,0,0,1,1,1,1,0,0,1,0,0,0,1,1,1,0,1,1,1,1])})
df_alt = df.copy()
def filter_df(df, colname, window_size):
    rolling_func = lambda z: z.sum() >= window_size
    df[colname] = pd.rolling_apply(df[colname],
                                    window_size,
                                    rolling_func,
                                    min_periods=window_size/2,
                                    center = True) 

def filter_alt(df, colname, window_size):
    rolling_func = lambda z: z.sum() >= window_size
    return scipy.ndimage.filters.generic_filter(df[colname].values,
                                                rolling_func,
                                                size = window_size,                                       
                                                origin = 0)

window_size = 4
filter_df(df, 'x', window_size)
print df
filter_alt(df_alt, 'x', window_size)


2 commentaires

Comment voudriez-vous traiter une séquence de mêmes valeurs plus longtemps que la taille de la fenêtre? Les valeurs sont-elles toujours identiques ou peuvent-elles différer pour le même tableau?


Je voudrais les garder comme une série de 1 aussi. Comme: [1,1,1,1,1] -> [1,1,1,1,1]


5 Réponses :


2
votes

Vous pouvez utiliser itheroTools.groupby comme suit: xxx

sortie xxx


3 commentaires

C'est aussi une bonne solution et je crois un peu plus vite que celui que j'ai fourni.


Merci Lambo Je vais tester votre solution aussi et voir qui fonctionne mieux.


iTertools Groupby est étonnamment rapide sur mes dataframes plutôt gros. J'ai testé 10000 itérations contre la solution de johnchase et il a réalisé beaucoup de mémoire et d'exécution. Je vais donc considérer cela la meilleure solution. Bien que John soit assez agréable mais manque de performance. Merci néanmoins!



1
votes

Il y a peut-être très bien une meilleure solution, mais je pense que cela devrait fonctionner:

In [96]: result
Out[96]: array([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1])


1 commentaires

Merci pour la réponse. Cela semble assez élégant, je vais l'essayer sur mon ensemble de données et voir comment cela fonctionne.



2
votes

Voici une approche en utilisant pd.rolling_min et des tours de foulée: xxx

alors nous avons: xxx

Sur les grandes matrices, cette approche est assez rapide (sur mon système de groupeBy est d'environ 20 fois plus lent): xxx


4 commentaires

Oui AJCR que j'ai essayé et c'était le plus lent. La solution ITERTOOLS est de loin le plus rapide. Aroung 13,9 MS par boucle sur mon jeu de données, Johns prend environ 153 ms par boucle et le vôtre près de 3 secondes. Merci.


@pho: J'ai remplacé rolling_apply avec rolling_min juste après que j'ai demandé (j'avais collé la mauvaise fonction - excuses). Il devrait être de manière significative plus rapide sur tout ensemble de données plus grand.


J'ai également eu une erreur dans ma fonction de groupeby modifiée qui explique que c'est si rapide. Je vais tester tout le monde demain une fois de plus. Merci ajcr


@pho a ajouté des tests d'exécution ici . La méthode de groupeBy semble beaucoup plus lente par rapport à la méthode des progrès.



1
votes

une variation plus compacte sur le iTertools.groupby solution: xxx


0 commentaires

8
votes

C'est fondamentalement un Fonctionnement de fermeture d'image dans le traitement de l'image code> pour un cas 1D cependant. Ces opérations pourraient être mises en œuvre avec des méthodes de convolution. Maintenant, Numpy prend en charge 1D Convolution , donc nous avons de la chance! Ainsi, pour résoudre notre cas, ce serait quelque chose comme ça -

In [541]: A = np.random.randint(0,2,(100000))

In [542]: WSZ = 4

In [543]: %timeit groupby_app(A,WSZ)
10 loops, best of 3: 74.5 ms per loop

In [544]: %timeit stride_tricks_app(A,WSZ)
100 loops, best of 3: 3.35 ms per loop

In [545]: %timeit conv_app(A,WSZ)
100 loops, best of 3: 2.82 ms per loop


1 commentaires

J'aurais dû savoir que vous trouveriez un moyen rapide! Je pensais brièvement à la convolution, mais je ne pensais pas à l'appliquer deux fois. Belle solution.