435 Stimmen

Konvertieren Sie ein Pandas DataFrame in ein Dictionary

Ich habe ein DataFrame mit vier Spalten. Ich möchte dieses DataFrame in ein Python-Wörterbuch umwandeln. Ich möchte, dass die Elemente der ersten Spalte keys sind und die Elemente der anderen Spalten in der gleichen Zeile values sind.

DataFrame:

    ID   A   B   C
0   p    1   3   2
1   q    4   3   2
2   r    4   0   9 

Die Ausgabe sollte so aussehen:

{'p': [1,3,2], 'q': [4,3,2], 'r': [4,0,9]}

8voto

Victoria Stuart Punkte 3912

Für meine Verwendung (Knotennamen mit xy-Positionen) fand ich die Antwort von @user4179775 am hilfreichsten / intuitivsten:

import pandas as pd

df = pd.read_csv('glycolysis_nodes_xy.tsv', sep='\t')

df.head()
    nodes    x    y
0  c00033  146  958
1  c00031  601  195
...

xy_dict_list=dict([(i,[a,b]) for i, a,b in zip(df.nodes, df.x,df.y)])

xy_dict_list
{'c00022': [483, 868],
 'c00024': [146, 868],
 ... }

xy_dict_tuples=dict([(i,(a,b)) for i, a,b in zip(df.nodes, df.x,df.y)])

xy_dict_tuples
{'c00022': (483, 868),
 'c00024': (146, 868),
 ... }

Zusatz

Später kehrte ich zu diesem Thema zurück, für andere, aber verwandte Arbeiten. Hier ist ein Ansatz, der der [ausgezeichneten] akzeptierten Antwort näher kommt.

node_df = pd.read_csv('node_prop-glycolysis_tca-from_pg.tsv', sep='\t')

node_df.head()
   node  kegg_id kegg_cid            name  wt  vis
0  22    22       c00022   pyruvate        1   1
1  24    24       c00024   acetyl-CoA      1   1
...

Ein Pandas-Datenframe in eine [Liste], {Dictionary}, {Dictionary von {Dictionary}}, ... umwandeln

Nach der akzeptierten Antwort:

node_df.set_index('kegg_cid').T.to_dict('list')

{'c00022': [22, 22, 'pyruvate', 1, 1],
 'c00024': [24, 24, 'acetyl-CoA', 1, 1],
 ... }

node_df.set_index('kegg_cid').T.to_dict('dict')

{'c00022': {'kegg_id': 22, 'name': 'pyruvate', 'node': 22, 'vis': 1, 'wt': 1},
 'c00024': {'kegg_id': 24, 'name': 'acetyl-CoA', 'node': 24, 'vis': 1, 'wt': 1},
 ... }

In meinem Fall wollte ich dasselbe tun, jedoch mit ausgewählten Spalten aus dem Pandas-Datenframe, daher musste ich die Spalten ausschneiden. Es gibt zwei Ansätze.

  1. Direkt:

(siehe: Pandas in ein Dictionary umwandeln und dabei die für die Schlüsselwerte verwendeten Spalten definieren)

node_df.set_index('kegg_cid')[['name', 'wt', 'vis']].T.to_dict('dict')

{'c00022': {'name': 'pyruvate', 'vis': 1, 'wt': 1},
 'c00024': {'name': 'acetyl-CoA', 'vis': 1, 'wt': 1},
 ... }
  1. "Indirekt:" zunächst die gewünschten Spalten/Daten aus dem Pandas-Datenframe ausschneiden (erneut zwei Ansätze),

    node_df_sliced = node_df[['kegg_cid', 'name', 'wt', 'vis']]

oder

node_df_sliced2 = node_df.loc[:, ['kegg_cid', 'name', 'wt', 'vis']]

die dann verwendet werden können, um ein Dictionary von Dictionaries zu erstellen

node_df_sliced.set_index('kegg_cid').T.to_dict('dict')

{'c00022': {'name': 'pyruvate', 'vis': 1, 'wt': 1},
 'c00024': {'name': 'acetyl-CoA', 'vis': 1, 'wt': 1},
 ... }

4voto

Ka Wa Yip Punkte 2556

Die meisten Antworten gehen nicht auf die Situation ein, in der die ID mehrmals im Datenrahmen vorhanden sein kann. Wenn die ID im Datenrahmen df dupliziert werden kann, möchten Sie eine Liste verwenden, um die Werte (auch bekannt als eine Liste von Listen) gruppiert nach ID zu speichern:

{k: [g['A'].tolist(), g['B'].tolist(), g['C'].tolist()] for k,g in df.groupby('ID')}

3voto

melon Punkte 41

Wörterbuchverständnis & Iterrows() Methode könnten auch verwendet werden, um die gewünschte Ausgabe zu erhalten.

result = {row.ID: [row.A, row.B, row.C] for (index, row) in df.iterrows()}

2voto

not a robot Punkte 3525

Wenn IDs eindeutig sind

set_index().T.to_dict() ist eine sehr einfache Syntax, aber das Transponieren eines DataFrame ist wirklich langsam. Die Syntax dict(zip(...)) ist etwa 70-mal schneller. Zum Beispiel dauert es für einen Rahmen mit 1 Million Zeilen weniger als 0,5 Sekunden, während set_index.T.to_dict über 30 Sekunden dauert.

mydict = dict(zip(df['ID'], df.set_index('ID').values.tolist()))

Auch eine Dictionary-Abbildung mit itertuples ist wirklich schnell (vorgeschlagen von Kamil Sindi), aber etwa 3-mal langsamer als dict(zip(...)).

mydict = {x[0]: list(x[1:]) for x in df.itertuples(index=False)}

Wenn IDs dupliziert sind

itertuples ist besonders nützlich, wenn die ID-Spalte doppelte Werte enthält. Es ist viel schneller, durch den DataFrame über itertuples zu iterieren und ein Dictionary mit dict.setdefault zu erstellen als über groupby (was von Ka Wa Yip vorgeschlagen wurde) oder iterrows. Zum Beispiel, für einen DataFrame mit 100k Zeilen und 60k eindeutigen IDs ist itertuples 250-mal schneller als groupby.1

mydict = {}
for row in df.itertuples(index=False):
    mydict.setdefault(row[0], []).append(list(row[1:]))
Leistungsbenchmarks:

Wie das Laufzeitdiagramm zeigt, sind dict(zip(...)) und itertuples mit dict.setdefault erheblich schneller als ihre "pandas" Pendants, egal wie groß die Rahmen sind.

perfplot

Code, um die obigen Diagramme zu erstellen:

import numpy as np
from perfplot import plot

plot(
    setup=lambda n: pd.DataFrame({'ID': np.arange(n)}).join(pd.DataFrame(np.random.default_rng().choice(10, size=(n, 3)), columns=[*'ABC'])),
    kernels=[lambda df: dict(zip(df['ID'], df.set_index('ID').values.tolist())), 
             lambda df: df.set_index('ID').T.to_dict('list'), 
             lambda df: {x[0]: list(x[1:]) for x in df.itertuples(index=False)}],
    labels= ["dict(zip(df['ID'], df.set_index('ID').values.tolist()))", 
             "df.set_index('ID').T.to_dict('list')", 
             "{x[0]: list(x[1:]) for x in df.itertuples(index=False)}"],
    n_range=[2**k for k in range(18)],
    xlabel='Number of rows',
    title='Unique IDs',
    equality_check=lambda x,y: x==y);

def itertuples_(df):
    mydict = {}
    for row in df.itertuples(index=False):
        mydict.setdefault(row[0], []).append(list(row[1:]))
    return mydict

def groupby_(df):
    return {k: g[['A', 'B', 'C']].values.tolist() for k, g in df.groupby('ID')}

plot(
    setup=lambda n: pd.DataFrame(np.random.default_rng().choice(n, size=(n, 4)), columns=['ID','A','B','C']),
    kernels=[itertuples_, groupby_],
    labels= ["itertuples", "groupby"],
    n_range=[2**k for k in range(17)],
    xlabel="Number of rows",
    title="Duplicated IDs",
    equality_check=lambda x,y: x==y);

1voto

shahar_m Punkte 3127
df = pd.DataFrame([['p',1,3,2], ['q',4,3,2], ['r',4,0,9]], columns=['ID','A','B','C'])
my_dict = {k:list(v) for k,v in zip(df['ID'], df.drop(columns='ID').values)}
print(my_dict)

mit Ausgabe

{'p': [1, 3, 2], 'q': [4, 3, 2], 'r': [4, 0, 9]}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X