2016-02-29 89 views
4

我正在尋找一種方法來優化我的代碼。從數據框中的列中提取字典值

我有條目數據以這種形式:

import pandas as pn 

a=[{'Feature1': 'aa1','Feature2': 'bb1','Feature3': 'cc2' }, 
{'Feature1': 'aa2','Feature2': 'bb2' }, 
{'Feature1': 'aa1','Feature2': 'cc1' } 
] 
b=['num1','num2','num3'] 


df= pn.DataFrame({'num':b, 'dic':a }) 

我想在上述數據幀列「DIC」(如果存在的話)從詞典中提取元件「特徵3」。到目前爲止,我能夠解決它,但我不知道這是否是最快的方式,它似乎有點過於複雜。

Feature3=[] 
for idx, row in df['dic'].iteritems(): 
    l=row.keys() 

    if 'Feature3' in l: 
     Feature3.append(row['Feature3']) 
    else: 
     Feature3.append(None) 

df['Feature3']=Feature3 
print df 

是否有更好/更快/更簡單的方法提取此Feature3以分隔數據框中的列?

非常感謝您的幫助。

+0

還有就是要檢查這是你存儲在您的DF非標量值沒有向量化的方法,這是不明智的,因爲它它使過濾和查找困難,因爲你發現 – EdChum

回答

4

您可以使用列表理解從數據框的每一行中提取特徵3,並返回一個列表。

feature3 = [d.get('Feature3') for d in df.dic] 

如果'Feature3'不在dic中,默認返回None。

你甚至不需要熊貓。

feature3 = [d.get('Feature3') for d in a] 
+0

這當然是一個非常「pythonic」的方式來做到這一點......並超過熊貓解決方案一個數量級 – maxymoo

1

我覺得你可以先通過comprehension創造新DataFrame然後像創建新列:

df1 = pd.DataFrame([x for x in df['dic']]) 
print df1 
    Feature1 Feature2 Feature3 
0  aa1  bb1  cc2 
1  aa2  bb2  NaN 
2  aa1  cc1  NaN 

df['Feature3'] = df1['Feature3'] 
print df 
               dic num Feature3 
0 {u'Feature2': u'bb1', u'Feature3': u'cc2', u'F... num1  cc2 
1   {u'Feature2': u'bb2', u'Feature1': u'aa2'} num2  NaN 
2   {u'Feature2': u'cc1', u'Feature1': u'aa1'} num3  NaN 

或者一個行:

df['Feature3'] = pd.DataFrame([x for x in df['dic']])['Feature3'] 
print df 
               dic num Feature3 
0 {u'Feature2': u'bb1', u'Feature3': u'cc2', u'F... num1  cc2 
1   {u'Feature2': u'bb2', u'Feature1': u'aa2'} num2  NaN 
2   {u'Feature2': u'cc1', u'Feature1': u'aa1'} num3  NaN 

時序

len(df) = 3

In [24]: %timeit pd.DataFrame([x for x in df['dic']]) 
The slowest run took 4.63 times longer than the fastest. This could mean that an intermediate result is being cached 
1000 loops, best of 3: 596 µs per loop 

In [25]: %timeit df.dic.apply(pn.Series) 
1000 loops, best of 3: 1.43 ms per loop 

len(df) = 3000

In [27]: %timeit pd.DataFrame([x for x in df['dic']]) 
100 loops, best of 3: 3.16 ms per loop 

In [28]: %timeit df.dic.apply(pn.Series) 
1 loops, best of 3: 748 ms per loop 
2

如果apply一個Series,你會得到一個相當不錯的DataFrame

>>> df.dic.apply(pn.Series) 
    Feature1 Feature2 Feature3 
0 aa1 bb1 cc2 
1 aa2 bb2 NaN 
2 aa1 cc1 NaN 

從這一點,你可以使用普通的熊貓操作。

1

我想你在考慮數據結構有點不對。最好從一開始就創建具有列作爲列的數據框;熊貓實際上是足夠聰明,在默認情況下做到這一點:

In [240]: pd.DataFrame(a) 
Out[240]: 
    Feature1 Feature2 Feature3 
0  aa1  bb1  cc2 
1  aa2  bb2  NaN 
2  aa1  cc1  NaN 

這樣,你會增加您的「編號」列在單獨的步驟,因爲數據是在一個不同的方向,無論是與

df['num'] = b 

df = df.assign(num = b) 

(我更喜歡第二個選項,因爲它具有更多功能的味道)。

2
df['Feature3'] = df['dic'].apply(lambda x: x.get('Feature3')) 

同意maxymoo。考慮改變數據幀的格式。

(旁註:大熊貓一般進口爲PD)