エントリの長さが異なるディクショナリからデータフレームを作成する


114

10個のキーと値のペアを持つ辞書があるとします。各エントリは、numpy配列を保持します。ただし、配列の長さはそれらすべてで同じではありません。

各列が異なるエントリを保持するデータフレームを作成するにはどうすればよいですか?

私が試したとき:

pd.DataFrame(my_dict)

私は得ます:

ValueError: arrays must all be the same length

これを克服する方法はありますか?Pandas NaNに短い列の列を埋めるために使用してもらえてうれしいです。

回答:


132

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

Python 2.xの場合:

置き換えるd.items()d.iteritems()


私は最近この同じ問題に取り組んでおり、これは私が持っていたものよりも優れています!注意すべきことの1つは、NaNをパディングすると、系列のdtypeがfloat64に強制変換されるため、整数演算を実行する必要がある場合に問題になる可能性があります。
mattexx 2013年

uはいつでも質問できます-多くの人が答えます
Jeff

コメントが示唆するように、MVCEを提供する必要があります
ジェフ

3
@germ最初にシリーズをインポートするか、またはpd.Series(...)import pandas as pdインポートセクションで想定)のような処理を実行する場合があります
Nima Mousavi '27

5
この回答のよりコンパクトなバージョン:pd.DataFrame({k: pd.Series(l) for k, l in d.items()})
user553965

82

これを行う簡単な方法を次に示します。

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

「インデックス付け」する他のオプションはありますか?
sAguinaga 2018

@sAguinagaはい:columnsですが、これはすでにデフォルトです。pandasのドキュメントを
Murmel

15

構文を整理する方法ですが、基本的にこれらの他の回答と同じことを行いますが、以下のとおりです。

>>> 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

リストにも同様の構文が存在します。

>>> 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

リストのもう1つの構文は次のとおりです。

>>> 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

さらに、結果を転置したり、列のデータ型(float、integerなど)を変更したりする必要がある場合があります。


3

これはOPの質問に直接答えるものではありませんが。これは、配列が等しくなく、共有したい場合に、私の場合に最適なソリューションであることがわかりました。

パンダのドキュメントから

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

オブジェクトのリストとpd.concat一緒に使用することもできます:axis=1pd.Series

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

次の両方の行は完全に機能します。

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

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

しかし、Jupyterで%timeitを使用すると、BとAの速度が4倍になります。これは、特に大量のデータセット(主に多数の列/機能)で作業する場合に非常に印象的です。


1

表示したくない場合でNaN、長さが2つある場合は、残りの各セルに「スペース」を追加しても機能します。

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   

エントリの長さが2を超える場合は、同様の方法を使用する関数を作成することをお勧めします。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.