Tạo khung dữ liệu từ từ điển nơi các mục nhập có độ dài khác nhau


114

Giả sử tôi có một từ điển với 10 cặp khóa-giá trị. Mỗi mục nhập chứa một mảng numpy. Tuy nhiên, độ dài của mảng không giống nhau cho tất cả chúng.

Làm cách nào để tạo khung dữ liệu trong đó mỗi cột chứa một mục nhập khác nhau?

Khi tôi thử:

pd.DataFrame(my_dict)

Tôi có:

ValueError: arrays must all be the same length

Bất kỳ cách nào để vượt qua điều này? Tôi rất vui khi được sử dụng Gấu trúc NaNđể đệm các cột đó cho các mục ngắn hơn.

Câu trả lời:


132

Trong 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

Trong Python 2.x:

thay thế d.items()bằng d.iteritems().


Tôi đã giải quyết vấn đề tương tự gần đây, và điều này tốt hơn những gì tôi có! Một điều cần lưu ý, đệm bằng NaN sẽ ép buộc loại chuỗi thành float64, điều này có thể gây ra vấn đề nếu bạn cần thực hiện phép toán số nguyên.
mattexx

u luôn có thể đặt một câu hỏi - rất nhiều người trả lời họ
Jeff

bạn cần phải cung cấp MVCE như các ý kiến đề nghị
Jeff

3
@germ bạn có thể muốn nhập Series đầu tiên hoặc làm điều gì đó như pd.Series(...) (giả sử import pandas as pdtrong phần nhập khẩu)
Nima Mousavi

5
Phiên bản nhỏ gọn hơn của câu trả lời này:pd.DataFrame({k: pd.Series(l) for k, l in d.items()})
user553965 Ngày

82

Đây là một cách đơn giản để làm điều đó:

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

có các tùy chọn khác để 'lập chỉ mục' không?
sAguinaga

@sAguinaga Có:, columnsnhưng đây đã là mặc định. Xem tài liệu về gấu trúc - pandas.DataFrame.from_dict
Murmel

15

Dưới đây là một cách sắp xếp gọn gàng cú pháp của bạn, nhưng vẫn thực hiện điều tương tự như các câu trả lời khác sau:

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

Một cú pháp tương tự cũng tồn tại cho danh sách:

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

Một cú pháp khác cho danh sách là:

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

Ngoài ra, bạn có thể phải chuyển đổi kết quả và / hoặc thay đổi các kiểu dữ liệu cột (float, integer, v.v.).


3

Trong khi điều này không trực tiếp trả lời câu hỏi của OP. Tôi thấy đây là một giải pháp tuyệt vời cho trường hợp của tôi khi tôi có các mảng không bằng nhau và tôi muốn chia sẻ:

từ tài liệu về gấu trúc

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

Bạn cũng có thể sử dụng pd.concatcùng axis=1với danh sách các pd.Seriesđối tượng:

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

Cả hai dòng sau đều hoạt động hoàn hảo:

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

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

Nhưng với% timeit trên Jupyter, tôi đã có tỷ lệ tốc độ 4x cho B vs A, khá ấn tượng, đặc biệt là khi làm việc với một tập dữ liệu khổng lồ (chủ yếu với một số lượng lớn các cột / tính năng).


1

Nếu bạn không muốn nó hiển thị NaNvà bạn có hai độ dài cụ thể, việc thêm 'khoảng trắng' vào mỗi ô còn lại cũng sẽ hoạt động.

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   

Nếu bạn có nhiều hơn 2 độ dài mục nhập, bạn nên tạo một hàm sử dụng phương thức tương tự.


-3

pd.DataFrame ([my_dict]) sẽ làm được!


không nếu các mảng trong dict có độ dài khác nhau
baxx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.