2013-08-10 9 views
19

Tôi có một cuốn từ điển python xếp hạng sử dụng mục mà trông giống như sau:Pandas khung dữ liệu từ điển

sample={'user1': {'item1': 2.5, 'item2': 3.5, 'item3': 3.0, 'item4': 3.5, 'item5': 2.5, 'item6': 3.0}, 
'user2': {'item1': 2.5, 'item2': 3.0, 'item3': 3.5, 'item4': 4.0}, 
'user3': {'item2':4.5,'item5':1.0,'item6':4.0}} 

tôi đang tìm kiếm để chuyển đổi nó thành một khung dữ liệu gấu trúc đó sẽ được cấu trúc như

 col1 col2 col3 
0 user1 item1 2.5 
1 user1 item2 3.5 
2 user1 item3 3.0 
3 user1 item4 3.5 
4 user1 item5 2.5 
5 user1 item6 3.0 
6 user2 item1 2.5 
7 user2 item2 3.0 
8 user2 item3 3.5 
9 user2 item4 4.0 
10 user3 item2 4.5 
11 user3 item5 1.0 
12 user3 item6 4.0 

Bất kỳ ý tưởng nào cũng sẽ được đánh giá cao :)

Trả lời

18

Hãy thử đoạn mã sau:

import pandas 

sample={'user1': {'item1': 2.5, 'item2': 3.5, 'item3': 3.0, 'item4': 3.5, 'item5': 2.5, 'item6': 3.0}, 
     'user2': {'item1': 2.5, 'item2': 3.0, 'item3': 3.5, 'item4': 4.0}, 
     'user3': {'item2':4.5,'item5':1.0,'item6':4.0}} 

df = pandas.DataFrame([ 
    [col1,col2,col3] for col1, d in sample.items() for col2, col3 in d.items() 
]) 
+0

Tuyệt vời. Cảm ơn :) – Godel

+1

Tuyệt vời, Nhưng làm thế nào để phản đối nhiệm vụ. tức là nếu dataframe được cung cấp cách chuyển đổi nó thành từ điển. Ngoài ra, nếu cột được bỏ ngẫu nhiên. – SujitS

+1

@BlackRabbitt, Sử dụng dict mặc định 'từ bộ sưu tập import defaultdict; d = defaultdict (dict); đối với người dùng, mục, giá trị trong df.values: d.setdefault (người dùng, {}) [item] = value' – falsetru

0

Bạn có thể thử làm như thế này.

temp=[] 
for item in sample: 
    temp.append(pandas.DataFrame(item)) 
self.results = pandas.concat(temp) 
+1

Cảm ơn phản hồi nhanh chóng. Khi tôi thử điều này, tôi nhận được lỗi sau Lần truy nguyên (cuộc gọi gần đây nhất): Tệp "", dòng 2, trong Tệp "pandas \ core \ frame.py", dòng 450, trong __init__ tăng PandasError ('Hàm tạo DataFrame không được gọi đúng!') pandas.core.common.PandasError: hàm tạo DataFrame không được gọi đúng! – Godel

13

Tôi nghĩ rằng hoạt động bạn đang sau - để UNPIVOT một bảng - được gọi là "tan chảy". Trong trường hợp này, phần cứng có thể được thực hiện bằng cách pd.melt, và mọi thứ khác về cơ bản là đổi tên và sắp xếp lại:

df = pd.DataFrame(sample).reset_index().rename(columns={"index": "item"}) 
df = pd.melt(df, "item", var_name="user").dropna() 
df = df[["user", "item", "value"]].reset_index(drop=True) 

Đơn giản chỉ cần gọi DataFrame sản xuất cái gì đó mà có các thông tin chúng tôi muốn nhưng có hình dạng sai:

>>> df = pd.DataFrame(sample) 
>>> df 
     user1 user2 user3 
item1 2.5 2.5 NaN 
item2 3.5 3.0 4.5 
item3 3.0 3.5 NaN 
item4 3.5 4.0 NaN 
item5 2.5 NaN 1.0 
item6 3.0 NaN 4.0 

Vì vậy, hãy thúc đẩy chỉ số cho một cột thực và cải thiện tên:

>>> df = pd.DataFrame(sample).reset_index().rename(columns={"index": "item"}) 
>>> df 
    item user1 user2 user3 
0 item1 2.5 2.5 NaN 
1 item2 3.5 3.0 4.5 
2 item3 3.0 3.5 NaN 
3 item4 3.5 4.0 NaN 
4 item5 2.5 NaN 1.0 
5 item6 3.0 NaN 4.0 

Sau đó, chúng tôi có thể gọi pd.melt để chuyển các cột. Nếu chúng ta không chỉ định tên biến mà chúng ta muốn, "người dùng", nó sẽ cho nó tên nhàm chán của "biến" (giống như nó cung cấp cho chính dữ liệu tên "giá trị" nhàm chán).

>>> df = pd.melt(df, "item", var_name="user").dropna() 
>>> df 
    item user value 
0 item1 user1 2.5 
1 item2 user1 3.5 
2 item3 user1 3.0 
3 item4 user1 3.5 
4 item5 user1 2.5 
5 item6 user1 3.0 
6 item1 user2 2.5 
7 item2 user2 3.0 
8 item3 user2 3.5 
9 item4 user2 4.0 
13 item2 user3 4.5 
16 item5 user3 1.0 
17 item6 user3 4.0 

Cuối cùng, chúng ta có thể sắp xếp lại và ghi số lại các chỉ số:

>>> df = df[["user", "item", "value"]].reset_index(drop=True) 
>>> df 
    user item value 
0 user1 item1 2.5 
1 user1 item2 3.5 
2 user1 item3 3.0 
3 user1 item4 3.5 
4 user1 item5 2.5 
5 user1 item6 3.0 
6 user2 item1 2.5 
7 user2 item2 3.0 
8 user2 item3 3.5 
9 user2 item4 4.0 
10 user3 item2 4.5 
11 user3 item5 1.0 
12 user3 item6 4.0 

melt là khá hữu ích khi bạn đã quen với nó. Thông thường, như ở đây, bạn làm một số đổi tên/sắp xếp lại trước và sau.

+0

Tôi nghĩ rằng điều này cũng nên được gọi là unpivot ... có thể trong 0,13! :) –

2

Cái này rất giống với các giải pháp melt cung cấp bởi DSM:

df = DataFrame(sample) 
df = df.unstack().dropna().reset_index() 
df = df.rename(columns={'level_0':'col1', 'level_1':'col2', 0:'col3'}) 
5

tôi cung cấp một khả năng khác ở đây sử dụng pd.stack:

df = pd.DataFrame(sample) 
df = df.T.stack().reset_index() 

Chi tiết giải thích

In [24]: df = pd.DataFrame(sample) 

In [25]: df 
Out[25]: 
     user1 user2 user3 
item1 2.5 2.5 NaN 
item2 3.5 3.0 4.5 
item3 3.0 3.5 NaN 
item4 3.5 4.0 NaN 
item5 2.5 NaN 1.0 
item6 3.0 NaN 4.0 

Áp dụng stack sẽ xoay trục cột trên trục phụ của trục hàng đã được lập chỉ mục bởi item.Như bạn muốn user đầu tiên, chúng ta hãy làm các hoạt động trên DataFrame hoán bằng cách sử dụng .T:

In [34]: df = df.T.stack() 

In [35]: df 
Out[35]: 
user1 item1 2.5 
     item2 3.5 
     item3 3.0 
     item4 3.5 
     item5 2.5 
     item6 3.0 
user2 item1 2.5 
     item2 3.0 
     item3 3.5 
     item4 4.0 
user3 item2 4.5 
     item5 1.0 
     item6 4.0 
dtype: float64 

Bạn mong đợi cột cơ bản và không chỉ số, vì vậy chỉ cần đặt lại chỉ mục:

In [36]: df = df.reset_index() 

In [37]: df 
Out[37]: 
    level_0 level_1 0 
0 user1 item1 2.5 
1 user1 item2 3.5 
2 user1 item3 3.0 
3 user1 item4 3.5 
4 user1 item5 2.5 
5 user1 item6 3.0 
6 user2 item1 2.5 
7 user2 item2 3.0 
8 user2 item3 3.5 
9 user2 item4 4.0 
10 user3 item2 4.5 
11 user3 item5 1.0 
12 user3 item6 4.0