2017-01-18 4 views
1

ich ein Datenrahmen df haben, das hat sieht wie folgt aus:Datenrahmen zu Wörterbuch der Liste von Tupeln von gruppierten Schlüssel

 a b c d 
0  8 xx 17 1.0 
1  8 xy 19 1.0 
2  8 zz 13 0.0 
3  9 tt 8 5.0 

Ich versuche, ein Wörterbuch zu erstellen, die einen Schlüssel mit einer Liste von Tupeln hat wie die folgenden:

{8:[(17,1.0),(19,1.0),(13,0.0)], 9:[(8,5.0)]} 

Hier kommt der Schlüssel aus der Spalte a und die Liste von Tupeln sind die Spalte c und d Spalte, die Schlüssel als haben. Ich beantrage diese auf andere Datensätze als auch und

df_new = df.groupby(['a'])[['c','d']).apply(lambda x: [tuple(x) for x in x.values]) 

jedoch versucht haben, ich bekomme immer den Fehler

raise TypeError('Series.name must be a hashable type') 
TypeError: Series.name must be a hashable type 

ich versucht habe, zu entfernen [ ‚a‘] in der groupby und halten es als 'a' wie folgt:

df_new = df.groupby('a')[['c','d']).apply(lambda x: [tuple(x) for x in x.values]) 

Aber ich bekomme die gleichen folgenden Fehler:

raise TypeError('Series.name must be a hashable type') 
TypeError: Series.name must be a hashable type 

Ich möchte nicht alles im ursprünglichen Datenrahmen df unveränderlich machen. Ich möchte es so behalten wie es ist.

Gibt es eine Möglichkeit, dies mit Pandas-Funktionalität zu erreichen? Ich möchte wirklich keine Listen erstellen und dann einige nach ihrem Index zusammenfügen und daraus ein Diktat erstellen.

+0

Was ist Ihre Pandas Version? 'print (pd.show_versionen())'? – jezrael

Antwort

2

Ich denke, es Fehler, aber arbeiten apply mit zip:

df = pd.DataFrame({'d': [1.0, 1.0, 0.0, 5.0], 
        'b': ['xx', 'xy', 'zz', 'tt'], 
        'a': [8, 8, 8, 9], 
        'c': [17, 19, 13, 8]}) 
print (df) 
    a b c d 
0 8 xx 17 1.0 
1 8 xy 19 1.0 
2 8 zz 13 0.0 
3 9 tt 8 5.0 

df_new = df.groupby(['a']).apply(lambda x: list(zip(x.c, x.d))).to_dict() 
print (df_new) 
{8: [(17, 1.0), (19, 1.0), (13, 0.0)], 9: [(8, 5.0)]} 

Für mich Ihre Version funktioniert (es gab kleine Tippfehler, ) zu ] geändert wurde):

df_new = df.groupby('a')[['c','d']].apply(lambda x: [tuple(x) for x in x.values]).to_dict() 
print (df_new) 
{8: [(17.0, 1.0), (19.0, 1.0), (13.0, 0.0)], 9: [(8.0, 5.0)]} 
2

Sie kann ein Wörterbuchverständnis verwenden:

{k: list(map(tuple, g[['c','d']].values)) for k, g in df.groupby('a')} 
# {8: [(17, 1), (19, 1), (13, 0)], 9: [(8, 5)]} 

Oder eine andere Art und Weise:

dict((k, list(map(tuple, g[['c','d']].values))) for k, g in df.groupby('a')) 
+0

Das sagt mir "['a'] nicht im Index" –

2

mit defaultdict

from collections import defaultdict 

d = defaultdict(list) 
for tup in df.itertuples(): 
    d[tup.a].append((tup.c, tup.d)) 

dict(d) 

{8: [(17, 1.0), (19, 1.0), (13, 0.0)], 9: [(8, 5.0)]} 

* mit to_dict und groupby *

df.set_index(['c', 'd']).groupby('a').apply(lambda df: df.index.tolist()).to_dict() 

{8: [(17, 1.0), (19, 1.0), (13, 0.0)], 9: [(8, 5.0)]} 
3

Nur eine weitere leichte Variation

df.set_index('a')[['c', 'd']]\ 
    .apply(tuple, 1)\ 
    .groupby(level=0)\ 
    .apply(list)\ 
    .to_dict() 

{8: [(17, 1), (19, 1), (13, 0)], 9: [(8, 5)]} 
Verwandte Themen