将字典列表字符串转换为数据框

时间:2018-11-27 07:37:20

标签: pandas python-2.7 dictionary dataframe

这是df1:

     indexID    detail                                             object
0          0  [{'y2': 627, 'frame': 1, 'visibility': 0, 'y1'...  Pedestrian
1          3  [{'y2': 699, 'frame': 1, 'visibility': 0, 'y1'...  Pedestrian
2          6  [{'y2': 852, 'frame': 1, 'visibility': 0, 'y1'...  Pedestrian
3          9  [{'y2': 595, 'frame': 1, 'visibility': 0, 'y1'...  Pedestrian
4         12  [{'y2': 629, 'frame': 1, 'visibility': 0, 'y1'...  Pedestrian
5         14  [{'y2': 586, 'frame': 7385, 'visibility': 0, '...  Pedestrian

仔细查看“详细信息”中的第一个单元格:

[{'y2': 627, 'frame': 1, 'visibility': 0, 'y1': 603, 'score': 1, 'x2': 770, 'x1': 759, 'class': 1}, {'y2': 623, 'frame': 2, 'visibility': 0, 'y1': 599, 'score': 1, 'x2': 777, 'x1': 766, 'class': 1}]

我正在尝试将df1转换为新的数据帧,其中新数据帧的每一行对应于df1中词典列表的一个字典,同时保留indexID。

假设已将转换数据帧的功能应用于df1的第一行,则转换后的数据帧将如下所示:

frame   indexID x1  y1  x2  y2  score   class   visibility
  1         0   759 603 770 627   1       1          0
  2         0   766 599 777 623   1       1          0

注意事项

  • 当我在终端上打印数据框时,它表明detail列是字典列表,如上所示。但是,当我运行type(df1['detail'][0])时,它将返回<type 'str'>
  • 详细信息列中每行有2个以上的字典。

我尝试将字符串转换为词典列表:

for index,row in df1.iterrows():
            print ast.literal_eval(row['detail'])

但是,我遇到了这个错误:

Traceback (most recent call last):
  File "main.py", line 283, in <module>
    print ast.literal_eval(row['detail'])
  File "/usr/lib/python2.7/ast.py", line 80, in literal_eval
    return _convert(node_or_string)
  File "/usr/lib/python2.7/ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string

Link for CSV

2 个答案:

答案 0 :(得分:0)

尝试一下

t=[{'y2': 627, 'frame': 1, 'visibility': 0, 'y1': 603, 'score': 1, 'x2': 770, 'x1': 759, 'class': 1}, {'y2': 623, 'frame': 2, 'visibility': 0, 'y1': 599, 'score': 1, 'x2': 777, 'x1': 766, 'class': 1}]
ind=df['indexID'].values

new_df= pd.DataFrame(t,index=ind)
print new_df

输出:

   class  frame  score  visibility   x1   x2   y1   y2
0      1      1      1           0  759  770  603  627
3      1      2      1           0  766  777  599  623

说明:

首先从列表中创建一个数据框,然后在外部分配索引。

EDIT-1:

df['detail']=df['detail'].apply(lambda x: ast.literal_eval(x))
print pd.DataFrame(sum(df['detail'].values,[]),index=df['indexID'].values)

输入:

   indexID                                         detail      object
0        0     [{'y2': 627, 'frame': 1, 'visibility': 0}]  Pedestrian
1        3     [{'y2': 699, 'frame': 1, 'visibility': 0}]  Pedestrian
2        6     [{'y2': 852, 'frame': 1, 'visibility': 0}]  Pedestrian
3        9     [{'y2': 595, 'frame': 1, 'visibility': 0}]  Pedestrian
4       12     [{'y2': 629, 'frame': 1, 'visibility': 0}]  Pedestrian
5       14  [{'y2': 586, 'frame': 7385, 'visibility': 0}]  Pedestrian

输出:

    frame  visibility   y2
0       1           0  627
3       1           0  699
6       1           0  852
9       1           0  595
12      1           0  629
14   7385           0  586

答案 1 :(得分:0)

您可以在使用ast.literal_eval之前进行一些预处理-将][替换为],[并转换为tuple,然后对列表进行扁平化处理:

import ast

df = pd.read_csv('test.csv', index_col=0)

df['detail'] = df['detail'].str.replace('][','],[', regex=False).apply(ast.literal_eval)
df['detail'] = [x if isinstance(x, tuple) else (x, ) for x in df['detail']]
#print (df)

s = df.set_index('indexID')['detail']
comp = {'{}_{}'.format(k, i): pd.DataFrame(x) for k, v in s.items() for i, x in enumerate(v)}
df = pd.concat(comp)
print (df.head())

       class  frame  score  visibility   x1   x2   y1   y2
0_0 0      1      1      1         0.0  759  770  603  627
    1      1      2      1         0.0  766  777  599  623
    2      1      3      1         0.0  770  786  593  618
    3      1      4      1         0.0  781  792  583  607
    4      1      5      1         0.0  786  800  573  597