การสร้างดาต้าเฟรมจากพจนานุกรมที่รายการมีความยาวต่างกัน


114

สมมติว่าฉันมีพจนานุกรมที่มีคู่คีย์ - ค่า 10 คู่ แต่ละรายการมีอาร์เรย์จำนวนนับ อย่างไรก็ตามความยาวของอาร์เรย์ไม่เท่ากันสำหรับทุกคน

ฉันจะสร้างดาต้าเฟรมโดยที่แต่ละคอลัมน์มีรายการที่แตกต่างกันได้อย่างไร

เมื่อฉันลอง:

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().


เมื่อเร็ว ๆ นี้ฉันกำลังแก้ไขปัญหาเดียวกันนี้และดีกว่าที่ฉันมี! สิ่งหนึ่งที่ควรทราบการเติมด้วย NaN จะทำให้อนุกรม dtype เป็น float64 ซึ่งอาจเป็นปัญหาได้หากคุณต้องการคำนวณจำนวนเต็ม
mattexx

คุณสามารถถามคำถามได้เสมอ - มีคนตอบคำถามมากมาย
เจฟฟ์

คุณต้องให้ MVCE ตามความคิดเห็นที่แนะนำ
Jeff

3
@germ คุณอาจต้องการนำเข้าซีรีส์ก่อนหรือทำสิ่งที่ต้องการpd.Series(...) (สมมติว่าimport pandas as pdอยู่ในส่วนการนำเข้า)
Nima Mousavi

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

@sAguinaga ใช่: columnsแต่นี่เป็นค่าเริ่มต้นแล้ว ดูเอกสารแพนด้า - pandas.DataFrame.from_dict
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

ไวยากรณ์อื่นสำหรับรายการคือ:

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

นอกจากนี้คุณอาจต้องเปลี่ยนผลลัพธ์และ / หรือเปลี่ยนชนิดข้อมูลคอลัมน์ (ลอยจำนวนเต็ม ฯลฯ )


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=1กับรายการpd.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)

แต่ด้วย% timeit บน Jupyter ฉันมีอัตราส่วนความเร็ว 4x สำหรับ B vs A ซึ่งค่อนข้างน่าประทับใจโดยเฉพาะเมื่อทำงานกับชุดข้อมูลขนาดใหญ่ (ส่วนใหญ่มีคอลัมน์ / คุณสมบัติจำนวนมาก)


1

หากคุณไม่ต้องการให้แสดงNaNและคุณมีความยาวสองความยาวการเพิ่ม 'ช่องว่าง' ในแต่ละเซลล์ที่เหลือก็จะใช้ได้เช่นกัน

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.