2016-12-01 13 views
0

Angesichts eines nach Monat indizierten Datenrahmens möchte ich am Tag neu indizieren (upsample). Werte, die zuvor nach Monat indiziert wurden, sollten jetzt durch die Anzahl der Tage im Monat dividiert werden. Zusätzlich zum Index sollte eine Spalte in der Gruppierung verwendet werden. Ähnlich wie this - nur mit einer Spalte, die auch in der Gruppierung verwendet wird.Upsampling Dataframe in Pandas mit Index + Spalte

import pandas as pd 
import numpy as np 

np.random.seed(1234) 
tidx_m = pd.date_range('2011-01-31', periods=5, freq='M') 
df = pd.DataFrame(np.random.randint(0, 2, (5, 2)), columns=['class', 'val']) 
df.index = tidx_m 
df = pd.concat([df, df]) 
df.ix[:5, 'class'] = 0 
df.ix[5:, 'class'] = 1 
print(df) 

      class val 
2011-01-31  0 1 
2011-02-28  0 1 
2011-03-31  0 0 
2011-04-30  0 1 
2011-05-31  0 1 
2011-01-31  1 1 
2011-02-28  1 1 
2011-03-31  1 0 
2011-04-30  1 1 
2011-05-31  1 1 

Nach Upsampling des Index anstelle von Monaten auf Tage, würde ich von dem Datetime-Index zu einer Gruppe wie undclass. Werte in "val" sollten an allen Tagen im Monat neu verteilt werden (z. B. wird 1 für jeden Tag im Januar 1/31).

+0

Können Sie Beispieldaten und gewünschte Ausgabe hinzufügen? – jezrael

+1

In realen Daten sind Duplikate im Index? Ist es möglich, 'df = pd.concat ([df, df])' wegzulassen? – jezrael

+0

Und danke für Probe. – jezrael

Antwort

1

Zuerst ist es notwendig, eine neue Zeile zu DataFrame mit Werten der ersten Zeile und Indexwert mit gleichem Index nur am ersten Tag des Monats hinzuzufügen.

Dann Spalte teilen val von DatetimeIndex.day und letzten Einsatz groupby mit resample und ffill neuen Werten.

df.val = df.val.div(df.index.day) 

first_idx = df.index[0] - pd.offsets.MonthBegin(1) 
print (first_idx) 
2011-01-01 00:00:00 

first_class_val = df.iloc[0] 
print (first_class_val) 
class 0.000000 
val  0.032258 
Name: 2011-01-31 00:00:00, dtype: float64 

df.loc[ first_idx] = first_class_val 
print (df) 
      class  val 
2011-01-31 0.0 0.032258 
2011-02-28 0.0 0.035714 
2011-03-31 0.0 0.000000 
2011-04-30 0.0 0.033333 
2011-05-31 0.0 0.032258 
2011-01-31 1.0 0.032258 
2011-02-28 1.0 0.035714 
2011-03-31 1.0 0.000000 
2011-04-30 1.0 0.033333 
2011-05-31 1.0 0.032258 
2011-01-01 0.0 0.032258 
df1 = df.groupby('class').resample('D').ffill().reset_index(level=0, drop=True) 

print (df1) 
      class  val 
2011-01-01 0.0 0.032258 
2011-01-02 0.0 0.032258 
2011-01-03 0.0 0.032258 
2011-01-04 0.0 0.032258 
2011-01-05 0.0 0.032258 
2011-01-06 0.0 0.032258 
2011-01-07 0.0 0.032258 
2011-01-08 0.0 0.032258 
2011-01-09 0.0 0.032258 
2011-01-10 0.0 0.032258 
2011-01-11 0.0 0.032258 
2011-01-12 0.0 0.032258 
2011-01-13 0.0 0.032258 
2011-01-14 0.0 0.032258 
2011-01-15 0.0 0.032258 
... 
... 
+0

Dies scheint mehrere Tage nur für Monate zu bieten, die auf Januar folgen. Ich erwarte 31 Tage für Januar. Da das erste "val" in Jan "1" ist, sollte jedes val nach der Operation 1/31 sein. –

+0

Auch die gleiche Klasse für einen Tag in einem beliebigen Monat sollte den gleichen Wert haben, da das "val" des Monats erhalten wird geteilt unter den Tagen in diesem Monat/Klassenkombination. –

+0

Ich bearbeite Antwort, bitte überprüfen Sie es. – jezrael