2017-07-04 2 views
4

Ich habe folgenden Datenrahmen:Berechne den Mittelwert der n-ten Anzahl der Elemente in der Spalte in pandas

   df1 
index year week a  b  c 
-10 2017 10 45 26 19 
    -9 2017 11 37 23 14 
    -8 2017 12 21 66 19 
    -7 2017 13 47 36 92 
    -6 2017 14 82 65 18 
    -5 2017 15 68 68 19 
    -4 2017 16 30 95 24 
    -3 2017 17 21 15 94 
    -2 2017 18 67 30 16 
    -1 2017 19 10 13 13 
    0 2017 20 26 22 18 
    1 2017 21 NaN NaN NaN 
    2 2017 22 NaN NaN NaN 
    3 2017 23 NaN NaN NaN 
    4 2017 24 NaN NaN NaN 
    ... 
    53 2018 20 NaN NaN NaN 

I für jede leere Zelle benötigen den Mittelwert der n-ten vorherigen Werte in einer Spalte zu berechnen und schreibe diesen Wert in eine Zelle. n ist gleich der Anzahl der Indizes von Null und höher. Zum Beispiel muss ich für die erste leere Zelle in der Spalte a den Durchschnitt zwischen den Indizes 0 und -10 berechnen. Dann für die nächste Zelle zwischen 1 und und so weiter. Dies gilt auch für die Spalten a, b und c. Und Berechnungen beginnen immer dort, wo die index = 1.

Und das Problem ist, dass die Anzahl der Spalten wie a, b, c kann unterschiedlich sein. Aber ich weiß, dass diese Spalten immer nach der Spalte week sind. Ist es möglich, diese Berechnungen auf eine unbestimmte Anzahl von Spalten anzuwenden, aber wenn es bekannt ist, dass diese Spalten nach der Spalte week liegen?

Ich habe mich bemüht, etwas zu finden, aber ich konnte nichts passendes finden.

UPD: Wenn das hilft, wird die maximale Anzahl von Zeilen von index = 0 und unten 53 sein.

+0

Wenn Sie sagen, „dann für die nächste Zelle zwischen '1' und' -9' und so weiter“, bedeutet es, a) berechnen den Mittelwert zwischen' -9 'und' 0' und ignoriere 'NaN' in '1' oder b) berechne den Mittelwert zwischen' -9' und '1' unter Verwendung des neuen Wertes, der für' 1' in der vorherigen "Iteration" berechnet wurde? – jdehesa

+0

@jdehesa, ja, ich muss auch einen neuen Wert in der Zelle '1' verwenden, wie Sie in b) beschrieben haben. –

+1

Sie können tatsächlich loc mit Slicing-Operatoren verwenden und dann ablassen, um nur die Spalten a, b, c zu erhalten (df1.loc [:, 'week':]. Drop ('week', axis = 1). Ich denke, theres no pandas Lösung (es sei denn, ein Pandas Zauberer kommt mit einem), um den gleitenden Durchschnittsgedanken zu machen (da du den vorherigen berechneten Durchschnitt mittelst) und du musst wahrscheinlich eine Pythonschleife verwenden. Wenn die Leistung kritisch ist, könntest du einen Blick darauf werfen Cython oder Numba, um die Schleife zu beschleunigen. –

Antwort

1

Sie können so etwas tun, indem Sie ein bisschen mit Pandas und Numpy herumspielen. Unter der Annahme, dass Sie wissen, was der Index der week Spalte sein wird (auch wenn Sie nicht, eine einfache Suche finden Sie den Index erhalten), wie beispielsweise die week Spalte 3. Sie können etwas tun wie

import numpy as np 
import pandas as pd 
#data is your dataframe name 
column_list = list(data.columns.values)[3:] 
for column_name in column_list : 
    column = data[column_name].values 
    #converted pandas series to numpy series 
    for index in xrange(0,column.shape[0]): 
     #iterating over entries in the column 
     if np.isnan(column[index]): 
      column[index] = np.nanmean(column.take(range(index-10,index+1),mode='wrap')) 

Dies ist eine schlechte, unverschlüsselte Lösung, sollte aber gut funktionieren. Es wird alle NaN-Einträge durch die vorherigen 10 Einträge ersetzen. Wenn Sie stattdessen nur die vorherigen 10 ohne ein Wrap-around, wollte nehmen Sie einfach die ersten n für n weniger als 10, wie
new_df[index] = np.nanmean(new_df[max(0,index-10):index+1])

hoffte, das hilft!

2

Dies kann wie folgt geschehen: Sie

 year week a b c 
index       
1  2017 21 NaN NaN NaN 
2  2017 22 NaN NaN NaN 
3  2017 23 NaN NaN NaN 
4  2017 24 NaN NaN NaN 

dann:

in diesem Fall, dass
for s in list(df.index): # iterate through rows with nan values 
    for i in range(2,df.columns.size): # iterate through different cols ('a','b','c' or more) 
     df1.loc[s,df.columns[i]] = df1.loc[range(s-n,s),df.columns[i]].sum()/n 
print(df1) 

beachten Sie bitte, ich Ihr Beispiel gefolgt

n = 11 # in the example of your explanation 
df = df1.loc[range(1,df1.index[-1]+1)] # select rows from index 1 above 

df aussehen sollte und angenommen, dass year immer die erste Spalte undsein wirdimmer zweite, um alle Spalten nach week und index auszuwählen.auch der Index

Ausgabe:

 year week   a   b   c 
index            
-10 2017 10 45.000000 26.000000 19.000000 
-9  2017 11 37.000000 23.000000 14.000000 
-8  2017 12 21.000000 66.000000 19.000000 
-7  2017 13 47.000000 36.000000 92.000000 
-6  2017 14 82.000000 65.000000 18.000000 
-5  2017 15 68.000000 68.000000 19.000000 
-4  2017 16 30.000000 95.000000 24.000000 
-3  2017 17 21.000000 15.000000 94.000000 
-2  2017 18 67.000000 30.000000 16.000000 
-1  2017 19 10.000000 13.000000 13.000000 
0  2017 20 26.000000 22.000000 18.000000 
1  2017 21 41.272727 41.727273 31.454545 
2  2017 22 40.933884 43.157025 32.586777 
3  2017 23 41.291510 44.989482 34.276484 
4  2017 24 43.136193 43.079434 35.665255 
Verwandte Themen