2015-04-29 167 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