2017-02-19 1 views
1

Ich habe eine lange Datei (CSV) mit „Spaltennamen x-Wert“ Paare, die ich in eine pandas.DataFrame lesen möchteLese csv mit Spaltennamen x Wertepaaren

user_id col val 
00008901 1 55 
00008901 2 66 
00011501 1 77 
00011501 3 88 
00011501 4 99 

Das Ergebnis sollte wie folgt aussehen:

   1 2 3 4 
00008901 55 66 0 0 
00011501 77 0 88 99 

ich versuchte, es in eine Liste zu lesen und ein Datenrahmen aus es schaffen, aber Pandas abgestürzt, als ich 4,5 Millionen Elemente haben.

Was ist der beste Weg, das zu tun? Idealerweise direkt mit read_csv.

Antwort

1

Erste Verwendung read_csv für create DataFrame:

df = pd.to_csv('file.csv') 

brauchen Dann set_index mit unstack:

df1 = df.set_index(['user_id','col'])['val'].unstack(fill_value=0) 
print (df1) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 77 0 88 99 

Eine andere Lösung mit pivot, NaN-0 von fillna und letzte Besetzung zu int ersetzt:

df1 = df.pivot(index='user_id', columns='col', values='val').fillna(0).astype(int) 
print (df1) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 77 0 88 99 

Wenn bekommen Fehler:

"ValueError: Index contains duplicate entries, cannot reshape"

Es bedeutet, dass Sie einige Duplikate haben, so schnellste Lösung ist groupby mit unstack und einige aggreagte Funktion wie mean oder sum:

print (df.groupby(['user_id','col'])['val'].mean().unstack(fill_value=0)) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 77 0 88 99 

Besser es sehen in etwas csv geändert:

print (df) 
    user_id col val 
0  8901 1 55 
1  8901 2 66 
2 11501 1 77 > duplicates -> 11501 and 1 
3 11501 1 151 > duplicates -> 11501 and 1 
4 11501 3 88 
5 11501 4 99 


print (df.groupby(['user_id','col'])['val'].mean().unstack(fill_value=0)) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 114 0 88 99 

Eigentlich dachte ich, ich hätte keine Duplikate, aber herausgefunden, dass ich wirklich einige habe ... Ich konnte nicht ".mean" verwenden, da es kategorialen Wert ist, aber th gelöst e Problem, indem sie zuerst an der sortierten Tabelle suchen und dann nur den letzten Eintrag zu halten ... dann die (super!) Anwendung Lösung .. die ich noch voll ;-) verstehen muß

df.sort(columns=(['user_id','col'])) # optional for debugging 
df.drop_duplicates(subset=['user_id','col'], keep='last', inplace=True) 
df_table = df.set_index(['user_id','col'])['val'].unstack(fill_value=0) 
+0

Wow, das ist schon ein cooler Ansatz, den ich seit Tagen nicht gefunden habe! Das Problem ist, dass ich einen Fehler beim Entstapeln bekomme> "ValueError: Index enthält doppelte Einträge, kann nicht umformen" –

+0

Siehe aktualisierte Lösung, ich versuche, Problem zu erklären und Lösung zu bekommen. – jezrael

+0

Tolle Lösung, die ich seit Tagen nicht mehr finden konnte! Danke vielmals! –

0

Ich glaube nicht, dass es möglich ist, read_csv zu verwenden, um die CSV-Datei zu analysieren.

Sie können eine Datenstruktur wie Wörterbuch erstellen und verwenden sie einen Datenrahmen zu erstellen:

import pandas as pd 
from collections import defaultdict 
import csv 

data_dict = defaultdict(lambda: [0] * columns) 
columns = 4 
delimiter = ',' 

with open("my_csv.csv") as csv_file: 
    reader = csv.DictReader(csv_file,delimiter=delimiter) 
    for row in reader: 
     row_id = row["user_id"] 
     col = int(row["col"])-1 
     val = int(row["val"]) 
     data_dict[row_id][col] = val 

df = pd.DataFrame(data_dict.values(), index=data_dict.keys(), columns=range(1, columns+1)) 

Für eine CSV-Datei, die enthält:

user_id,col,val 
00008901,1,55 
00008901,2,66 
00011501,1,77 
00011501,3,88 
00011501,4,99 

Die Ausgabe lautet:

  1 2 3 4 
00008901 55 66 0 0 
00011501 77 0 88 99 
1

Sie können nicht direkt lesen Sie die benötigte Struktur mit read_csv. Aber Sie können pivot_table Funktion verwenden, um in die gewünschte Struktur zu konvertieren.

df = pd.read_csv('filepath/your.csv') 
df = pd.pivot_table(df, index='user_id', columns='col', values='val, aggfunc='mean').reset_index() 

The output will be like 
      1 2 3 4 
00008901 55 66 0 0 
00011501 77 0 88 99 
+0

Sieht nach einer interessanten Alternative aus. In meinem Fall kann ich einfach nicht "gemein" verwenden, da ich kategorische Werte habe, sondern nur die letzte beibehalten muss (siehe oben). –

Verwandte Themen