2016-05-13 7 views
0

Ich habe vier Pandas DataFrames (A, B, C und). A eine Reihe von Zeitmarken aufweist und eine einzige Spalte, die mit einer der anderen Datenrahmen bezeichnet:Bedingte Zusammenführung von anderen mehreren Pandas DataFrames

A 

Timestamp Source 
----------- ------ 
2012-4-3  B 
2013-12-20 C 
2012-3-5  C 
2014-12-7 D 
2012-7-10 B 
... 

Die anderen Datenrahmen mehr Daten enthalten:

B 

Timestamp Foo Bar 
----------- ---- ---- 
2012-1-1 1.5 1.3 
2012-1-2 2.3 5.6 
2012-1-3 3.4 3.3 
... 
2014-3-31 0.8 2.1 

C 

Timestamp Foo Bar 
----------- ---- ---- 
2012-1-1 9.2 5.6 
2012-1-2 4.8 7.6 
2012-1-3 2.7 6.4 
... 
2014-3-31 7.0 6.5 

D 

Timestamp Foo Bar 
----------- ---- ---- 
2012-1-1 6.8 4.2 
2012-1-2 4.2 9.3 
2012-1-3 5.5 0.7 
... 
2014-3-31 6.3 2.0 

I aus A einen einzelnen Datenrahmen konstruieren will, B, C und D, die drei Säulen (Timestamp, Foo und Bar), wobei die Werte von Foo und Bar aus dem entsprechenden 012.306.464 kommen hatim DataFrame aufgeführt als Source in A.

Nicht alle Zeitstempel in A erscheinen in den drei anderen Datenrahmen, wobei in diesem Fall ich die Werte von Foo möchte und Barnp.nan sein. Nicht alle Zeitstempel in B, C und erscheinen in A und werden einfach nicht im endgültigen DataFrame angezeigt.

My aktuelle Ansatz ist durch jede Reihe in einer Schleife und zurück um die Werte aus dem entsprechenden Source Datenrahmen:

srcs = {'B': B, 'C': C, 'D': D} 
A['Foo'] = np.nan 
A['Bar'] = np.nan 

for i in range(len(A)): 
    ts = A.iloc[i].Timestamp 
    src = A.iloc[i].Source 
    A.iloc[i].Foo = srcs[src][srcs[src].Timestamp == ts].Foo 
    A.iloc[i].Bar = srcs[src][srcs[src].Timestamp == ts].Bar 

hat sie eine effiziente sein, mehr Pandithic Weise, diese Aktion durchzuführen (?) ?

+0

Hmm, würde ein Verfahren zur Herstellung einer Spalte Quelle hinzufügen zu Jedes df mit B, C, D auf B, C, D jeweils und dann alle von ihnen auf TimeStamp und Source zusammenführen, nicht sicher, wie chaotisch wäre es aber – EdChum

+0

Würde dies nicht zu einem df mit 6 separaten Spalten führen (z.B. 'Foo_x', 'Bar_x', 'Foo_y', 'Bar_y', 'Foo', 'Bar')? Wie würde ich sie in zwei Spalten ("Foo" und "Bar") basierend auf der Quelle kombinieren? –

Antwort

2

Es sieht so aus, als könnten Sie dafür einen Multiindex verwenden. Ihr Index würde aus dem Zeitstempel und der Quelle bestehen. Du kannst dies mit der set_index Methode auf einem DataFrame tun.

Hier ist ein Code zum Erstellen einiger gefälschter DataFrames mit jeweils dem MultiIndex.

Jetzt können Sie die Quelldatensätze (B, C und D) mit dem Index auf A indizieren.

for s, df in sources.items():  

    temp = df.loc[A.index] # the source data set indexed by A's index 
          # this will contain NaN's where df does not 
          # have corresponding index entries 
    temp.dropna(inplace=True) # dropping the NaN values leaves you with 
          # only the values in df matching the index in A 
    if len(temp) > 0: 
     A.loc[temp.index] = temp # now assign the data to A 

print(A) 

Das Ergebnis sieht so aus:

     Bar  Foo 
TimeStamp Source      
0   D   NaN  NaN 
1   C   NaN  NaN 
2   D   NaN  NaN 
3   B  7.927154 8.581380 
4   B  7.638422 5.970348 
5   D   NaN  NaN 
6   C  6.938001 6.417248 
7   B   NaN  NaN 
8   C  5.131940 9.144621 
9   B   NaN  NaN 
10  D  9.186963 5.991877 
11  D  8.070543 7.735040 
12  C   NaN  NaN 
13  B   NaN  NaN 
14  C   NaN  NaN 
15  D   NaN  NaN 
16  C   NaN  NaN 
17  C   NaN  NaN 
18  C   NaN  NaN 
19  B   NaN  NaN 
1

Setup-

import pandas as pd 
from StringIO import StringIO 

texta = """Timestamp Source 
2012-4-3  B 
2012-4-2  B 
2013-12-20 C 
2012-3-5  C 
2014-12-7 D 
2012-7-10 B""" 

A = pd.read_csv(StringIO(texta), delim_whitespace=1, parse_dates=[0]) 

textb = """Timestamp Foo Bar 
2012-1-1 1.5 1.3 
2012-4-3 3.1 4.1 
2012-1-2 2.3 5.6 
2012-1-3 3.4 3.3 
2014-3-31 0.8 2.1""" 

B = pd.read_csv(StringIO(textb), delim_whitespace=1, parse_dates=[0]) 

textc = """Timestamp Foo Bar 
2012-1-1 9.2 5.6 
2012-3-5 4.8 7.6 
2012-1-2 4.8 7.6 
2012-1-3 2.7 6.4 
2014-3-31 7.0 6.5""" 

C = pd.read_csv(StringIO(textc), delim_whitespace=1, parse_dates=[0]) 

textd = """Timestamp Foo Bar 
2012-1-1 6.8 4.2 
2012-1-2 4.2 9.3 
2012-1-3 5.5 0.7 
2014-3-31 6.3 2.0""" 

D = pd.read_csv(StringIO(textd), delim_whitespace=1, parse_dates=[0]) 

Dann habe ich mit pd.concat nur BC und D

bdf = pd.concat([B, C, D], keys=['B', 'C', 'D']) 
bdf.reset_index(level=1, inplace=1, drop=1) 
bdf.index.name = 'Source' 
bdf.reset_index(inplace=1) 

print bdf 
kombinieren

Es sieht wie folgt aus:

Source Timestamp Foo Bar 
0  B 2012-01-01 1.5 1.3 
1  B 2012-04-03 3.1 4.1 
2  B 2012-01-02 2.3 5.6 
3  B 2012-01-03 3.4 3.3 
4  B 2014-03-31 0.8 2.1 
5  C 2012-01-01 9.2 5.6 
6  C 2012-03-05 4.8 7.6 
7  C 2012-01-02 4.8 7.6 
8  C 2012-01-03 2.7 6.4 
9  C 2014-03-31 7.0 6.5 
10  D 2012-01-01 6.8 4.2 
11  D 2012-01-02 4.2 9.3 
12  D 2012-01-03 5.5 0.7 
13  D 2014-03-31 6.3 2.0 

Schließlich

eine einfache Zusammenführung

A.merge(bdf, how='left') 

Sieht aus wie:

Timestamp Source Foo Bar 
0 2012-04-03  B 3.1 4.1 
1 2012-04-02  B NaN NaN 
2 2013-12-20  C NaN NaN 
3 2012-03-05  C 4.8 7.6 
4 2014-12-07  D NaN NaN 
5 2012-07-10  B NaN NaN 
Verwandte Themen