Erstellen eines Datenrahmens aus einem Wörterbuch, in dem Einträge unterschiedlich lang sind


114

Angenommen, ich habe ein Wörterbuch mit 10 Schlüssel-Wert-Paaren. Jeder Eintrag enthält ein Numpy-Array. Die Länge des Arrays ist jedoch nicht für alle gleich.

Wie kann ich einen Datenrahmen erstellen, in dem jede Spalte einen anderen Eintrag enthält?

Wenn ich es versuche:

pd.DataFrame(my_dict)

Ich bekomme:

ValueError: arrays must all be the same length

Wie kann man das überwinden? Ich bin froh, dass Pandas NaNdiese Spalten für die kürzeren Einträge auffüllen.

Antworten:


131

In Python 3.x:

In [6]: d = dict( A = np.array([1,2]), B = np.array([1,2,3,4]) )

In [7]: pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in d.items() ]))
Out[7]: 
    A  B
0   1  1
1   2  2
2 NaN  3
3 NaN  4

In Python 2.x:

ersetzen d.items()durch d.iteritems().


Ich habe kürzlich an demselben Problem gearbeitet, und das ist besser als das, was ich hatte! Beachten Sie, dass durch das Auffüllen mit NaNs der Typ dtype auf float64 gezwungen wird. Dies kann problematisch sein, wenn Sie ganzzahlige Berechnungen durchführen müssen.
Mattexx

Sie können immer eine Frage stellen - viele Leute beantworten sie
Jeff

Sie müssen MVCE bereitstellen, wie aus den Kommentaren hervorgeht
Jeff

3
@germ Vielleicht möchten Sie zuerst die Serie importieren oder etwas Ähnliches tun pd.Series(...) (vorausgesetzt, import pandas as pdim Importabschnitt)
Nima Mousavi

5
Kompaktere Version dieser Antwort: pd.DataFrame({k: pd.Series(l) for k, l in d.items()})
user553965

81

Hier ist eine einfache Möglichkeit, dies zu tun:

In[20]: my_dict = dict( A = np.array([1,2]), B = np.array([1,2,3,4]) )
In[21]: df = pd.DataFrame.from_dict(my_dict, orient='index')
In[22]: df
Out[22]: 
   0  1   2   3
A  1  2 NaN NaN
B  1  2   3   4
In[23]: df.transpose()
Out[23]: 
    A  B
0   1  1
1   2  2
2 NaN  3
3 NaN  4

Gibt es andere Optionen zum 'Indexieren'?
sAguinaga

@sAguinaga Ja: columnsaber das ist schon die Standardeinstellung. Siehe Pandas Dokumentation - Pandas.DataFrame.from_dict
Murmel

15

Im Folgenden finden Sie eine Möglichkeit, Ihre Syntax aufzuräumen, aber im Wesentlichen das Gleiche wie bei diesen anderen Antworten zu tun:

>>> mydict = {'one': [1,2,3], 2: [4,5,6,7], 3: 8}

>>> dict_df = pd.DataFrame({ key:pd.Series(value) for key, value in mydict.items() })

>>> dict_df

   one  2    3
0  1.0  4  8.0
1  2.0  5  NaN
2  3.0  6  NaN
3  NaN  7  NaN

Eine ähnliche Syntax gibt es auch für Listen:

>>> mylist = [ [1,2,3], [4,5], 6 ]

>>> list_df = pd.DataFrame([ pd.Series(value) for value in mylist ])

>>> list_df

     0    1    2
0  1.0  2.0  3.0
1  4.0  5.0  NaN
2  6.0  NaN  NaN

Eine andere Syntax für Listen lautet:

>>> mylist = [ [1,2,3], [4,5], 6 ]

>>> list_df = pd.DataFrame({ i:pd.Series(value) for i, value in enumerate(mylist) })

>>> list_df

   0    1    2
0  1  4.0  6.0
1  2  5.0  NaN
2  3  NaN  NaN

Möglicherweise müssen Sie das Ergebnis zusätzlich transponieren und / oder die Spaltendatentypen (float, integer usw.) ändern.


3

Dies beantwortet zwar nicht direkt die Frage des OP. Ich fand, dass dies eine hervorragende Lösung für meinen Fall ist, wenn ich ungleiche Arrays hatte und Folgendes mitteilen möchte:

aus der pandas dokumentation

In [31]: d = {'one' : Series([1., 2., 3.], index=['a', 'b', 'c']),
   ....:      'two' : Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
   ....: 

In [32]: df = DataFrame(d)

In [33]: df
Out[33]: 
   one  two
a    1    1
b    2    2
c    3    3
d  NaN    4

3

Sie können auch pd.concatzusammen axis=1mit einer Liste von pd.SeriesObjekten verwenden:

import pandas as pd, numpy as np

d = {'A': np.array([1,2]), 'B': np.array([1,2,3,4])}

res = pd.concat([pd.Series(v, name=k) for k, v in d.items()], axis=1)

print(res)

     A  B
0  1.0  1
1  2.0  2
2  NaN  3
3  NaN  4

2

Beide folgenden Zeilen funktionieren perfekt:

pd.DataFrame.from_dict(df, orient='index').transpose() #A

pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in df.items() ])) #B (Better)

Aber mit% timeit auf Jupyter habe ich ein Verhältnis von 4x Geschwindigkeit für B gegen A, was besonders bei der Arbeit mit einem riesigen Datensatz (hauptsächlich mit einer großen Anzahl von Spalten / Features) ziemlich beeindruckend ist.


1

Wenn Sie nicht möchten, dass es angezeigt wird NaNund Sie zwei bestimmte Längen haben, funktioniert das Hinzufügen eines Leerzeichens in jeder verbleibenden Zelle ebenfalls.

import pandas

long = [6, 4, 7, 3]
short = [5, 6]

for n in range(len(long) - len(short)):
    short.append(' ')

df = pd.DataFrame({'A':long, 'B':short}]
# Make sure Excel file exists in the working directory
datatoexcel = pd.ExcelWriter('example1.xlsx',engine = 'xlsxwriter')
df.to_excel(datatoexcel,sheet_name = 'Sheet1')
datatoexcel.save()

   A  B
0  6  5
1  4  6
2  7   
3  3   

Wenn Sie mehr als zwei Längen von Einträgen haben, ist es ratsam, eine Funktion zu erstellen, die eine ähnliche Methode verwendet.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.