Okay, gruppiert aggregieren, ich habe jetzt eine Zeit lang auf dieser gearbeitet und ich habe eine Lösung, aber es funktioniert nicht optimal. Hier ist ein Beispiel dafür, was die Datenrahmen wie folgt aussehen:Wie kann ich durch einen Wechsel-In-Zustand Spalte in einer Pandas Datenrahmen von Datetimes
print(month_df[['timestamp','date','hvac_state']].head(100))
timestamp date hvac_state
0 2017-11-09 18:43:45 12-09-17 off
1 2017-11-09 20:15:27 12-09-17 heating
2 2017-11-09 22:29:00 12-09-17 heating
3 2017-11-09 23:42:34 12-09-17 off
4 2017-11-10 00:09:40 12-10-17 heating
5 2017-11-10 00:23:14 12-10-17 heating
6 2017-11-10 03:32:17 12-10-17 off
7 2017-11-10 10:59:24 12-10-17 heating
8 2017-11-10 11:12:59 12-10-17 off
9 2017-11-10 13:49:09 12-10-17 off
10 2017-11-10 16:58:11 12-10-17 heating
11 2017-11-10 17:11:45 12-10-17 heating
12 2017-11-10 17:25:19 12-10-17 off
13 2017-11-10 23:53:44 12-10-17 off
14 2017-11-11 00:25:22 12-11-17 off
15 2017-11-11 03:29:53 12-11-17 heating
16 2017-11-11 03:43:26 12-11-17 heating
17 2017-11-11 04:01:31 12-11-17 off
Es gibt andere Felder in dem month_df Datenrahmen, aber diese sind die drei, die ich verwende. Eine Zeile wird angehängt, wenn sich etwas ändert. Manchmal ist die Änderung des Elements der hvac_state, manchmal ist es eine andere Spalte. Deshalb sehen Sie, dass sich der Zustand gelegentlich nicht ändert, aber es gibt einen anderen Eintrag.
Ich möchte für Tag alle „Mengen der Zeit“ und den Zustand der hvac_state Spalte aggregieren. Ich fand ein paar Artikel auf groupby und mit Shift (wie this one) und das ist, was ich umgesetzt, aber es ist nicht perfekt, weil der Tag Cutoffs nicht genau bei 00: 00: 00-23: 59: 59 für jeden Tag. Ich kann dies in meinen aggregierten Daten angeben, weil ich am Ende Mengen von etwas mehr als 24 Stunden erreiche. Außerdem ist es offensichtlich nicht effizient, da ich eine "Zeitmarke" und eine "Datum" -Spalte verwende, um dies durchzuführen.
Dies ist die Methode, die ich zur Zeit mit:
def remove_consecutive_duplicates(a):
return a.loc[a.shift() != a]
# Get the left data frame ready, with timestamps associated specifically with state changes.
left = remove_consecutive_duplicates(month_df.set_index('timestamp')['hvac_state']).reset_index()
# Then delta from change to change and shift by negative 1.
left['delta'] = left.timestamp.diff().fillna(0).astype(int).shift(-1).fillna(0)
# Now prep the right dataframe by hurling the hvac_state so we don't end up with two.
right = month_df.drop(['hvac_state'], axis=1)
# Perform the merge, dropping the stuff that isn't in the left side.
result = pd.merge(left, right, how='left', on='timestamp')
# Now we can store that month's hourly usage by day.
grouped = (result.groupby(['date','hvac_state'])[['delta']].sum()/3600000).round(2)
results = defaultdict(lambda: defaultdict(dict))
for index, value in grouped.itertuples():
for i, key in enumerate(index):
if i == 0:
nested = results[key]
elif i == len(index) - 1:
nested[key] = value
else:
nested = nested[key]
results
defaultdict(<function __main__.<lambda>>,
{'12-09-17': defaultdict(dict, {'heating': 3.84, 'off': 10.24}),
'12-10-17': defaultdict(dict, {'heating': 8.36, 'off': 14.39}),
'12-11-17': defaultdict(dict, {'heating': 10.17, 'off': 14.91}),
'12-12-17': defaultdict(dict, {'heating': 9.34, 'off': 13.56}),
'12-13-17': defaultdict(dict, {'heating': 10.49, 'off': 13.59}),
'12-14-17': defaultdict(dict, {'heating': 9.58, 'off': 14.72}),
'12-15-17': defaultdict(dict, {'heating': 6.03, 'off': 24.38}),
'12-16-17': defaultdict(dict, {'heating': 0.0})})
Sie sind von diesem Beispiel zu sehen, dass am 15. meine „off“ Zeit ist 24,38 Stunden, während die „Heizung“ Zeit ist 6,03 Stunden.
würde ich es vorziehen, einen Standard-Wörterbuch aus (für json Nutzung) erhalten mit dem Datum als Schlüssel und die Staaten wie die Unterschlüssel zu der Höhe der Zeit in jedem Zustand verbracht zeigen. Die Statuswerte sollten zu 24 Stunden hinzugefügt werden. Idealerweise so etwas wie diese:
{
'12-12-17': {'heating': 5.23, 'off': 18.77},
'12-13-17': {'heating': 7.85, 'off': 16.15},
'12-14-17': {'heating': 7.91, 'off': 16.09},
'12-15-17': {'heating': 6.22, 'off': 17.78},
'12-16-17': {'heating': 5.11, 'off': 18.89},
'12-17-17': {'heating': 9.17, 'off': 14.83}
}
Danke @Parfait! Das ist eine ausgezeichnete Erklärung und Methode! Ich benutze es definitiv. –
Ich habe es tatsächlich etwas modifiziert, indem ich die "Datum" -Spalte entferne, so dass ich nur 'Zeitstempel' brauche. Ich habe pd.DateOffset (days = 1) in midnights_df verschoben, weil es nach dem Festlegen der Zeitzone Probleme verursacht hat. @Parfait, du bist ein Gentleman und ein Gelehrter! –
Haha ... StackOverflow, das Geschenk, das weitergibt, wo das OP von einer veröffentlichten Lösung lernt und es auf die tatsächlichen Bedürfnisse ausdehnt (viele Poster wollen eine genaue Antwort auf Plug & Tuck). Freut mich, Ihnen bei Ihrer interessanten Frage zu helfen. Glückliche Kodierung! – Parfait