2016-07-31 10 views
0

ich ein paar Dateien txt, die alle die gleiche erste Spalte (X) und die gleichen Spaltennamen (X, B, C), aber die zweite und dritte Spalte sind unterschiedliche Werte.Kombination Dateien in Multiindex Datenrahmen in Python und exportieren schließlich

X | B | C 
----------- 
a 0 2 
b 4 9 
... 
z 3 0 

Ich möchte all diese Tabellen in einen großen Datenrahmen verbinden, aber mit dem Zusatz, dass jeder Teil ist über einen eigenen Index, zum Beispiel basierend auf den Dateinamen. Z.B. wäre [0, 4..., 3]. Das Endergebnis würde so aussehen.

| f1 | f1 | f2 | f2 
X | B | C | B | C 
----------------------- 
a 0 2 3 2 
b 4 9 1 2 
...   
z 3 0 9 8 

Dies ist der Code, den ich bisher habe

import pandas as pd 
import numpy as np 
import regex as re 

dir = 'directory' 
path = os.path.abspath(os.path.join(os.getcwd(), dir)) 
# List all files in folder 
filenames = [name for name in os.listdir(path) if re.match(".*\.txt$", name)] 

r_coln = re.compile(r"\.txt$") 

frames = [] 

for i in range(len(filenames)): 
    filename = filenames[i] 
    coln = r_coln.sub("", filename) 
    if (i == 0): 
     # Subtract the first column which is identical for all frames 
     first_frame = pd.read_csv(os.path.join(path, filename), usecols=[0], sep="\t", names=[''], header=None) 
     frames.append(first_frame) 

    # Get frame with a new header 
    frames.append(pd.read_csv(os.path.join(path, filename), usecols=[1, 2], sep="\t", names=[coln, ''], header=None)) 

# Combine all frames 
df = pd.concat(frames, axis=1) 

Dies funktioniert, dass der resultierende Datenrahmen in der Tat wie das Beispiel sieht die ich oben mit Ausnahme geschrieben, dass ich nur eine ‚top‘ habe Überschrift pro Datei. Die Verwendung von names=[coln, coln] anstelle von names=[coln, ''] führte dazu, dass eine der beiden Spalten gelöscht wurde (und ich weiß nicht warum). Es ist jedoch nicht multi-indiziert. Mit anderen Worten, ich kann nicht auf df['f1']['B'] zugreifen, weil es den Fehler KeyError: 'B' zurückgibt. Ich suche nach einer Möglichkeit, dies zu ermöglichen. Entweder durch Umwandlung der resultierenden df nach der Einleseschleife oder durch Ändern von etwas innerhalb der Schleife.

Schließlich möchte ich auch diesen Datenrahmen in eine Tab-getrennte Textdatei exportieren.

+1

Sie können das Argument 'keys' in' pd.concat' verwenden. Es erstellt automatisch einen Multi-Index und fügt eine höhere Ebene hinzu, die aus bestandenen Schlüsseln besteht. ('names' fügt Namen für die Ebenen hinzu.) Wahrscheinlich wollen Sie auch zuerst' X' als Index setzen - entweder mit der '.set_index' Methode oder mit dem' index_col' Argument zu 'pd.read_csv'. – ptrj

Antwort

0

Bearbeiten - Hinzufügen eines Einzeilers, Kredite zu @ ptrj.

df = pd.concat([df1.set_index('X'),df2.set_index('X')],axis=1,keys = ['F1','F2']) 

In []: df 
Out[]: 
     F1 F2 
    B C B C 
X 
a 0 2 0 4 
b 4 9 8 18 
z 3 0 6 0 

Alternative Lösung:

Sie können einen Multiindex von Arrays definieren.

Beginnen wir mit zwei Beispieldatenrahmen.

df1 = pd.DataFrame({'B': {0: 0, 1: 4, 2: 3}, 
        'C': {0: 2, 1: 9, 2: 0}, 
        'X': {0: 'a', 1: 'b', 2: 'z'}}) 

df2 = pd.DataFrame({'B': {0: 0, 1: 8, 2: 6}, 
        'C': {0: 4, 1: 18, 2: 0}, 
        'X': {0: 'a', 1: 'b', 2: 'z'}}) 

# Merge the DataFrames 
merged = df1.merge(df2,on='X').set_index('X') 

# Create a MultiIndex 
arrays = [['F1','F1','F2','F2'], ['B','C','B','C']] 
columns = pd.MultiIndex.from_arrays(arrays, names=['level1', 'level2']) 

# Create your DataFrame  

df = pd.DataFrame(data=merged.as_matrix(), 
        columns=columns, 
        index = df1['X']) 

df sieht nun wie:

level1 F1  F2 
level2 B C B C 
    X    
    a 0 2 0 4 
    b 4 9 8 18 
    z 3 0 6 0 

Jetzt können Sie indizieren df['F1']

level2 B C 
    X   
    a 0 2 
    b 4 9 
    z 3 0 

mit Oder df['F1']['B'], die Sie gibt:

0 0 
1 4 
2 3 

Bearbeiten: @ Bram Vanroy extended this solution mit mehreren DataFrames arbeiten.

+0

Nachdem Sie einige Tippfehler korrigiert haben, die Sie gemacht haben, funktioniert es. Die X-Spalten sind jedoch weiterhin sichtbar. –

+0

@BramVanroy - Entschuldigung! Ich habe einige Änderungen vorgenommen. Können Sie es noch einmal versuchen? – user666

+0

[Die X-Spalten sind jedoch weiterhin sichtbar] try ....... list (df ['F1'] ['B'].Werte) – Merlin