2017-10-09 2 views
2

Ich habe zwei DataFrames. Einer hat eine Reihe von Werten, die bestimmten Zeiten und Daten entsprechen (df_1). Die andere hat eine Reihe von Werten, die bestimmten Daten entsprechen (df_2). Ich möchte diese DataFrames so zusammenführen, dass die Werte von df_2 für Datumsangaben auf alle mal von df_1 für die entsprechenden Daten angewendet werden.Wie können DataFrames so zusammengeführt werden, dass die Werte von einem, die * Datumsangaben * entsprechen, auf alle * Zeiten * aller Daten des anderen angewendet werden?

So, hier ist df_1:

|DatetimeIndex   |value_1| 
|-----------------------|-------| 
|2015-07-18 13:53:33.280|10  | 
|2015-07-18 15:43:30.111|11  | 
|2015-07-19 13:54:03.330|12  | 
|2015-07-20 13:52:13.350|13  | 
|2015-07-20 16:10:01.901|14  | 
|2015-07-20 16:50:55.020|15  | 
|2015-07-21 13:56:03.126|16  | 
|2015-07-22 13:53:51.747|17  | 
|2015-07-22 19:45:14.647|18  | 
|2015-07-23 13:53:29.346|19  | 
|2015-07-23 20:00:30.100|20  | 

und hier ist df_2:

|DatetimeIndex|value_2| 
|-------------|-------| 
|2015-07-18 |100 | 
|2015-07-19 |200 | 
|2015-07-20 |300 | 
|2015-07-21 |400 | 
|2015-07-22 |500 | 
|2015-07-23 |600 | 

ich sie wie folgt zusammenführen möchten:

|DatetimeIndex   |value_1|value_2| 
|-----------------------|-------|-------| 
|2015-07-18 00:00:00.000|NaN |100 | 
|2015-07-18 13:53:33.280|10.0 |100 | 
|2015-07-18 15:43:30.111|11.0 |100 | 
|2015-07-19 00:00:00.000|NaN |200 | 
|2015-07-19 13:54:03.330|12.0 |200 | 
|2015-07-20 00:00:00.000|NaN |300 | 
|2015-07-20 13:52:13.350|13.0 |300 | 
|2015-07-20 16:10:01.901|14.0 |300 | 
|2015-07-20 16:50:55.020|15.0 |300 | 
|2015-07-21 00:00:00.000|NaN |400 | 
|2015-07-21 13:56:03.126|16.0 |400 | 
|2015-07-22 00:00:00.000|NaN |500 | 
|2015-07-22 13:53:51.747|17  |500 | 
|2015-07-22 19:45:14.647|18  |500 | 
|2015-07-23 00:00:00.000|NaN |600 | 
|2015-07-23 13:53:29.346|19  |600 | 
|2015-07-23 20:00:30.100|20  |600 | 

Also, die value_2 ganzen existiert die Tage.

Welche Art von Zusammenführung nennt man das? Wie kann es gemacht werden?

-Code für den Datenrahmen ist wie folgt:

import pandas as pd 

df_1 = pd.DataFrame(
    [ 
     [pd.Timestamp("2015-07-18 13:53:33.280"), 10], 
     [pd.Timestamp("2015-07-18 15:43:30.111"), 11], 
     [pd.Timestamp("2015-07-19 13:54:03.330"), 12], 
     [pd.Timestamp("2015-07-20 13:52:13.350"), 13], 
     [pd.Timestamp("2015-07-20 16:10:01.901"), 14], 
     [pd.Timestamp("2015-07-20 16:50:55.020"), 15], 
     [pd.Timestamp("2015-07-21 13:56:03.126"), 16], 
     [pd.Timestamp("2015-07-22 13:53:51.747"), 17], 
     [pd.Timestamp("2015-07-22 19:45:14.647"), 18], 
     [pd.Timestamp("2015-07-23 13:53:29.346"), 19], 
     [pd.Timestamp("2015-07-23 20:00:30.100"), 20] 
    ], 
    columns = [ 
     "datetime", 
     "value_1" 
    ] 
) 
df_1.index = df_1["datetime"] 
del df_1["datetime"] 
df_1.index = pd.to_datetime(df_1.index.values) 

df_2 = pd.DataFrame(
    [ 
     [pd.Timestamp("2015-07-18 00:00:00"), 100], 
     [pd.Timestamp("2015-07-19 00:00:00"), 200], 
     [pd.Timestamp("2015-07-20 00:00:00"), 300], 
     [pd.Timestamp("2015-07-21 00:00:00"), 400], 
     [pd.Timestamp("2015-07-22 00:00:00"), 500], 
     [pd.Timestamp("2015-07-23 00:00:00"), 600] 
    ], 
    columns = [ 
     "datetime", 
     "value_2" 
    ] 
) 
df_2 
df_2.index = df_2["datetime"] 
del df_2["datetime"] 
df_2.index = pd.to_datetime(df_2.index.values) 

Antwort

3

Lösung
einen neuen Index-Konstrukt, das eine Vereinigung der beiden ist. Dann wird eine Kombination aus reindex und map

idx = df_1.index.union(df_2.index) 

df_1.reindex(idx).assign(value_2=idx.floor('D').map(df_2.value_2.get)) 

         value_1 value_2 
2015-07-18 00:00:00.000  NaN  100 
2015-07-18 13:53:33.280  10.0  100 
2015-07-18 15:43:30.111  11.0  100 
2015-07-19 00:00:00.000  NaN  200 
2015-07-19 13:54:03.330  12.0  200 
2015-07-20 00:00:00.000  NaN  300 
2015-07-20 13:52:13.350  13.0  300 
2015-07-20 16:10:01.901  14.0  300 
2015-07-20 16:50:55.020  15.0  300 
2015-07-21 00:00:00.000  NaN  400 
2015-07-21 13:56:03.126  16.0  400 
2015-07-22 00:00:00.000  NaN  500 
2015-07-22 13:53:51.747  17.0  500 
2015-07-22 19:45:14.647  18.0  500 
2015-07-23 00:00:00.000  NaN  600 
2015-07-23 13:53:29.346  19.0  600 
2015-07-23 20:00:30.100  20.0  600 

Erklärung

  • die Vereinigung der beiden nehmen sollte selbsterklärend sein. Bei der Vereinigung erhalten wir automatisch einen sortierten Index. Das ist praktisch!
  • Wenn wir df_1 mit dieser neuen und verbesserten Vereinigung von Indizes neuindizieren, werden einige der Indexwerte nicht im Index df_1 enthalten sein. Ohne Angabe anderer Parameter werden die Spaltenwerte für die zuvor nicht vorhandenen Indizes np.nan sein, und genau dafür haben wir uns entschieden.
  • Ich verwende assign, um Spalten hinzuzufügen.
    • Ich denke, es sauberer ist
    • Es überschreibt die Datenrahmen ich arbeiten bin
    • Es Pipelines gut
  • idx.floor('D') mir den Tag gibt, während die Eigenschaft des Haltens eines pd.DatetimeIndex zu sein. Das erlaubt mir map direkt danach.
  • pd.Index.map nimmt eine aufrufbare
  • ich df_2.value_2.get geben, die viel wie dict.get fühlt (die Ich mag)

Antwort
Angenommen df_2 hat mehrere Spalten zu kommentieren. Wir konnten join statt

df_1.join(df_2.loc[idx.date].set_index(idx), how='outer') 

         value_1 value_2 
2015-07-18 00:00:00.000  NaN  100 
2015-07-18 13:53:33.280  10.0  100 
2015-07-18 15:43:30.111  11.0  100 
2015-07-19 00:00:00.000  NaN  200 
2015-07-19 13:54:03.330  12.0  200 
2015-07-20 00:00:00.000  NaN  300 
2015-07-20 13:52:13.350  13.0  300 
2015-07-20 16:10:01.901  14.0  300 
2015-07-20 16:50:55.020  15.0  300 
2015-07-21 00:00:00.000  NaN  400 
2015-07-21 13:56:03.126  16.0  400 
2015-07-22 00:00:00.000  NaN  500 
2015-07-22 13:53:51.747  17.0  500 
2015-07-22 19:45:14.647  18.0  500 
2015-07-23 00:00:00.000  NaN  600 
2015-07-23 13:53:29.346  19.0  600 
2015-07-23 20:00:30.100  20.0  600 

nutzen dies wie eine besser zu sein scheint in antworten, dass es kürzer ist. Aber es ist langsamer für den Fall der einzelnen Spalte. Verwenden Sie es auf jeden Fall für den mehrspaltigen Fall.

%timeit df_1.reindex(idx).assign(value_2=idx.floor('D').map(df_2.value_2.get)) 
%timeit df_1.join(df_2.loc[idx.date].set_index(idx), how='outer') 

1.56 ms ± 69 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 
2.38 ms ± 591 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 
+0

Ah das ist großartig. Vielen Dank für die ausführliche Erklärung. Besonders hilfreich war die Verwendung der Flut ('D'). Etwas peinliche Folgefrage (wenn es einfach zu beantworten ist): Sagen wir, ich habe tatsächlich * viele * Werte in jedem der DataFrames. Ist es möglich, auf diese Weise zu verschmelzen, ohne jede Variable "hart zu codieren"? – BlandCorporation

+0

Ja !. Gib mir einen Moment, um die Antwort zu aktualisieren. – piRSquared

+0

Hey, nochmals vielen Dank für die zusätzlichen Details. Es ist schön, die Effizienzinformationen zu sehen. – BlandCorporation

Verwandte Themen