2015-04-29 130 views
1

我有数据帧,其中一列是存储作为像这样的字符串的词典列表:删除字典

name age misc 
Jim 44 "[{"value":3,"type":"cars"},{"value":1,"type":"pets"},{"value":13,"type":"shoes"}]" 
Bob 25 "[{"value":3,"type":"siblings"},{"value":1,"type":"pets"}]" 
Sue 55 "[]" 

我想这其中每个类型变得很自己的列与相应的值:

name age cars pets shoes siblings 
Jim 44 3 1 13 0 
Bob 25 0 1 0  3 
Sue 55 0 0 0  0 

回答

1

步骤1:将字符串'列表'列到一个ctual列表:

from ast import literal_eval 

df['misc'] = [literal_eval(r) for r in df.misc] 

步骤2:循环遍历每个字典来获得 '价值'(例如汽车,宠物,鞋子等)。为每个唯一值添加一列到DataFrame。

sublists = [[d.get('type') for d in cell] for cell in df.misc] 
cols = list(set([item for sublist in sublists for item in sublist])) 
for c in cols: 
    df[c] = 0 

步骤3:创建一个词典,其得到值对于每种类型(假定有不超过一个类型的字典的行中一个给定的列表)。然后,通过这些价值数枚举和结果分配回数据框:

value_counts = [{d.get('type'): d.get('value') for d in cell} for cell in df.misc] 
for n, row in enumerate(value_counts): 
if row: 
    items, values = zip(*row.items()) 
    df.loc[df.index[n], items] = values 

del df['misc'] 

>>> df 
    name age cars shoes pets siblings 
0 Jim 44  3  13  1   0 
1 Bob 25  0  0  1   3 
2 Sue 55  0  0  0   0 
+0

这似乎很有希望,问题是我现在发现每个实际上都是字符串,所以它实际上是这样的:''[[“value”:3,“type”:“cars”},{“value” :1,“type”:“pets”},{“value”:13,“type”:“shoes”}]“' – user4843645

+0

您可以使用literal_eval将其转换回列表:from ast import literal_eval df ['misc '] = [在df.misc中为r的literal_eval(r)] – Alexander

0

我真的会在这里看到:http://pandas.pydata.org/pandas-docs/dev/api.html#dataframe。另外,您的数据的来源必须真正遍布整个地方,我会先重新格式化。因为你没有提供数据本身的原始来源,这里虽然创造你要找的假设更加结构化的数据源的数据帧的一个简单的例子:

>>> data = {'Bob':{'age':25, 'pets':1, 'siblings':3}, 'Jim':{'age':44, 'cars':3, 'pets': 1, 'shoes': 13}} 
>>> pd.DataFrame(data).T.fillna(0) 

    age cars pets shoes siblings 
Bob 25  0  1  0   3 
Jim 44  3  1  13   0 
1

这是最好的避免创建DataFrame,其列的值为 字典列表。但为了帮助您做到这一点,我们需要了解用于构建当前DataFrame的 数据的来源。

鉴于目前的数据帧,但是,您可以通过使用df['misc'].apply(func)调用一个函数,func,在df['misc']每个 值将其转换为所需的数据框 。

如果您安排此功能返回一个系列,则 df['misc'].apply(func)将返回一个DataFrame,其列对应于该系列的索引。例如,

def func(x): 
    try: 
     df = pd.DataFrame(ast.literal_eval(x)) 
     result = pd.Series(df['value'].values, index=df['type']) 
    except KeyError: 
     result = pd.Series() 
    return result 

attributes = df['misc'].apply(func) 
print(attributes) 

产生

cars pets shoes siblings 
0  3  1  13  NaN 
1 NaN  1 NaN   3 
2 NaN NaN NaN  NaN 

现在,我们可以用0取代的NaN:

attributes = attributes.fillna(0) 

df除去misc柱:

del df['misc'] 

和通过连接建立所需的数据帧dfattributes

df = pd.concat([df, attributes], axis=1) 

全部放在一起,

import numpy as np 
import pandas as pd 
import ast 

df = pd.DataFrame(
    [('Jim', 44, '''[{"value":3,"type":"cars"},{"value":1,"type":"pets"}, {"value":13,"type":"shoes"}]'''), 
    ('Bob', 25, '[{"value":3,"type":"siblings"},{"value":1,"type":"pets"}]'), 
    ('Sue', 55, '[]')], 
    columns=['name', 'age', 'misc']) 

def func(x): 
    try: 
     df = pd.DataFrame(ast.literal_eval(x)) 
     result = pd.Series(df['value'].values, index=df['type']) 
    except KeyError: 
     result = pd.Series() 
    return result 

attributes = df['misc'].apply(func) 
attributes = attributes.fillna(0) 
del df['misc'] 
df = pd.concat([df, attributes], axis=1) 
print(df) 

产量

name age cars pets shoes siblings 
0 Jim 44  3  1  13   0 
1 Bob 25  0  1  0   3 
2 Sue 55  0  0  0   0 
+0

完美的作品,但是当我尝试在我的设置(这是在相同的格式),我得到一个错误:'PandasError:数据帧的构造不正确地调用!' – user4843645

+0

听起来像misc列包含* strings *。最好从原始数据正确构建所需的DataFrame,而不是向后弯曲以修复当前的DataFrame,但如果必须的话,则可以使用'ast.literal_eval'将字符串转换为一个字典列表。我已编辑帖子以显示如何。 – unutbu