2016-07-23 10 views
1

Ich habe eine Dataframe Probe wie folgt:anwenden groupby Regeln auf Zeitreihen?

value=DataFrame({'A':[0,-1,0], 
        'B':[1,1,-1], 
        'C':[0,0,1], 
        'D':[-1,1,1]}) 
    value.index=pd.date_range('1/1/2016',periods=len(value),freq='M') 

Und ich möchte die Antwort haben, wie folgt:

answer=DataFrame({'A':[0,-1,0], 
         'B':[1,0.5,-0.5], 
         'C':[0,0,-0.5], 
         'D':[-1,0.5,1]}) 
    answer.index=pd.date_range('1/1/2016',periods=len(value),freq='M') 

Die Regel lautet:

Für jedes Datum, die Summe der Zeile ist Null, und das Gewicht wird gleichmäßig innerhalb jeder Wertkategorie von 0, -1 oder 1 aufgeteilt.

Zum Beispiel

  • Wenn es drei -1s, eine 1 ist, dann ist die Antwort -0.33, -0.33, -0.33,1
  • Wenn es nur eine 1 und drei -1s ist , dann ist die Antwort 1, -0.33, -0.33, -0.33
  • Wenn es zwei 1s ist, eine -1, ist die Antwort 0.5,0.5, -1,0

Antwort

1
import pandas as pd 

value = pd.DataFrame({'A':[0,-1,0], 
       'B':[1,1,-1], 
       'C':[0,0,1], 
       'D':[-1,1,1]}) 
value.index = pd.date_range('1/1/2016',periods=len(value),freq='M') 
pos = (value > 0) 
neg = (value < 0) 

result = ((value*pos).divide(pos.sum(axis=1), axis=0) 
      +(value*neg).divide(neg.sum(axis=1), axis=0)) 

print(result) 

ergibt

   A B C D 
2016-01-31 0.0 1.0 0.0 -1.0 
2016-02-29 -1.0 0.5 0.0 0.5 
2016-03-31 0.0 -1.0 0.5 0.5 

Beachten Sie, dass die letzte Zeile von result entspricht nicht answer, aber ich denke, es ist die Beschreibung passt, wenn ich es richtig verstehe.


pos und neg sind boolean Datenrahmen. pos, ist beispielsweise der Fall, wenn value positiv ist:

In [206]: pos 
Out[206]: 
       A  B  C  D 
2016-01-31 False True False False 
2016-02-29 False True False True 
2016-03-31 False False True True 

value*pos die gleiche wie value ist, wenn value positiv ist, und sonst Null:

In [207]: value*pos 
Out[207]: 
      A B C D 
2016-01-31 0 1 0 0 
2016-02-29 0 1 0 1 
2016-03-31 0 0 1 1 

pos.sum(axis=1) zählt die Anzahl der True Werte in jedem Reihe. Dividieren (value*pos) durch die Zählung erzeugt die gewünschte Gewichtung:

In [208]: (value*pos).divide(pos.sum(axis=1), axis=0) 
Out[208]: 
       A B C D 
2016-01-31 0.0 1.0 0.0 0.0 
2016-02-29 0.0 0.5 0.0 0.5 
2016-03-31 0.0 0.0 0.5 0.5 

Das gleiche gilt für die negativen Werte durchgeführt werden. Das Hinzufügen der positiven und negativen Teile ergibt das gewünschte Ergebnis.