从数据框中的列中提取字典值

时间:2016-02-29 22:32:12

标签: python pandas

我正在寻找一种优化代码的方法。

我有这种形式的输入数据:

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

我想提取元素' Feature3'来自上面数据框中的词典' dic'(如果存在)中的词典。到目前为止,我能够解决它,但我不知道这是否是最快的方式,它似乎有点过于复杂。

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提取到数据框中的单独列?

提前感谢您的帮助。

6 个答案:

答案 0 :(得分:12)

您可以使用列表推导从数据框中的每一行中提取特征3,并返回一个列表。

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

如果' Feature3'不在dic中,默认情况下它返回None。

您甚至不需要pandas,因为您可以再次使用列表解析从原始字典a中提取该功能。

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

答案 1 :(得分:4)

如果你apply Series,你会得到一个非常好的DataFrame

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

从这一点来说,你可以使用常规的pandas操作。

答案 2 :(得分:4)

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

同意maxymoo。请考虑更改数据框的格式。

(旁注:大熊猫一般以pd形式导入)

答案 3 :(得分:1)

我认为您可以先按DataFrame创建新的comprehension,然后创建新列,如:

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

答案 4 :(得分:1)

我认为你在考虑数据结构有点错误。最好从头开始创建具有列的功能的数据框; pandas实际上足够聪明,默认情况下这样做:

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

然后,您将在单独的步骤中添加“num”列,因为数据的方向不同,可以使用

df['num'] = b

df = df.assign(num = b)

(我更喜欢第二种选择,因为它有更多功能性的味道)。

答案 5 :(得分:0)

df = pd.concat([df, pd.DataFrame(list(df['dic']))], axis=1)

然后对结果做任何你想做的事情,如果某个地方缺少一个键,你会在那里得到 NaN。