2016-06-22 2 views
1

Ich versuche meine Daten zu bereinigen, indem ich in den ersten 2 Stunden jeder 'state'-Gruppe' value 'auf NaN setze.Pandas: Setze die ersten 2 Stunden jeder Gruppe auf NaN

Mein Datenrahmen sieht wie folgt aus:

>>> import pandas as pd 
>>> import numpy as np 
>>> 
>>> rng = pd.date_range('1/1/2016', periods=6, freq='H') 
>>> 
>>> data = {'value': np.random.rand(len(rng)), 
...   'state': ['State 1']*3 + ['State 2']*3} 
>>> df = pd.DataFrame(data, index=rng) 
>>> 
>>> df 
         state  value 
2016-01-01 00:00:00 State 1 0.800798 
2016-01-01 01:00:00 State 1 0.130290 
2016-01-01 02:00:00 State 1 0.464372 
2016-01-01 03:00:00 State 2 0.925445 
2016-01-01 04:00:00 State 2 0.732331 
2016-01-01 05:00:00 State 2 0.811541 

ich mit drei Möglichkeiten habe kommen, dies zu tun, und beide funktionieren nicht:

1) Erster Versuch mit .loc und/oder .ix zu keiner Änderung führen:

>>> df.loc[df.state=='State 2'].first('2H').value = np.nan 
>>> df.ix[df.state=='State 2'].first('2H').value = np.nan 
>>> df 
         state  value 
2016-01-01 00:00:00 State 1 0.800798 
2016-01-01 01:00:00 State 1 0.130290 
2016-01-01 02:00:00 State 1 0.464372 
2016-01-01 03:00:00 State 2 0.925445 
2016-01-01 04:00:00 State 2 0.732331 
2016-01-01 05:00:00 State 2 0.811541 

2) Zweiter Versuch führt zu einem Fehler:

>>> df.loc[df.state=='State 2', 'value'].first('2H') = np.nan 
    File "<stdin>", line 1 
SyntaxError: can't assign to function call 

3) Dies ist ein hackish Versuch, die funktioniert, ist aber offenbar entmutigt:

>>> temp = df.loc[df.state=='State 2'] 
>>> temp.first('2H').value = np.nan 
/home/user/anaconda3/lib/python3.5/site-packages/pandas/core/generic.py:2698: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame. 
Try using .loc[row_indexer,col_indexer] = value instead 

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy 
    self[name] = value 
>>> df.loc[df.state=='State 2'] = temp 
>>> df 
         state  value 
2016-01-01 00:00:00 State 1 0.800798 
2016-01-01 01:00:00 State 1 0.130290 
2016-01-01 02:00:00 State 1 0.464372 
2016-01-01 03:00:00 State 2  NaN 
2016-01-01 04:00:00 State 2  NaN 
2016-01-01 05:00:00 State 2 0.811541 

Idealerweise möchte ich über jede Gruppe eine einfache Möglichkeit, eine Schleife zu bestimmen und den Anfang und das Ende ihrer jeweiligen Datengruppen reinigen . Ich hatte den Eindruck, dass .first und .last aufgrund ihrer einfachen Time-String-Formate großartig wären.

Mit .loc berücksichtigt diese Zeit Zeichenfolge Formate nicht, aber ich vermisse wahrscheinlich etwas.

Was ist die wahre Art, dies in Pandas zu tun?

Antwort

1

Finden all indexes indem zuerst 2H, dann index zu Multiindex, ix und letzten reset_indexswaplevel ändern zum Anpassen:

idx = df.groupby('state')['value'].apply(lambda x: x.first('2H')).index 

df.set_index('state', append=True, inplace=True) 
df = df.swaplevel(0,1) 

df.ix[idx,'value'] = np.nan 

print (df.reset_index(level=0)) 
         state  value 
2016-01-01 00:00:00 State 1  NaN 
2016-01-01 01:00:00 State 1  NaN 
2016-01-01 02:00:00 State 1 0.406512 
2016-01-01 03:00:00 State 2  NaN 
2016-01-01 04:00:00 State 2  NaN 
2016-01-01 05:00:00 State 2 0.226350 
+0

Diese Antwort wird davon ausgegangen, dass die Daten gleichmäßig beabstandet sind und indiziert durch Stunden. Ich möchte die Funktion df.first ('2H') nutzen, um sich um eindeutige, aber inkonsistent beabstandete Daten zu kümmern. – cbcoutinho

+0

Antwort wurde bearbeitet, bitte überprüfen Sie es. – jezrael

+0

Unglaublich - das ist genau das, was ich gesucht habe. – cbcoutinho