加快数据帧从dict生成代码的速度

时间:2019-01-05 07:01:27

标签: python pandas

以下是我正在使用的实际dict的简化示例。转储到JSON文件时,实际的dict非常大(大约10 MB)。我正在尝试通过字典解析并将其转换为使用特定格式的数据框。目的是使用to_excel方法将此数据帧转储到excel中。

import pandas as pd

data = {'kvk_1':
            {'link_1':
                {'header_1':
                    {'body_1':'value_1', 
                    'body_2':'value_2',
                    'body_3':'value_3'},
                 'header_2':
                    {'body_4':'value_1',
                    'body_4':'value_3',
                    'body_5':'value_2'}
                    },
            'link_2':
                {'header_4':
                    {'body_7':'value_8',
                    'body_8':'value_9'},
                 'header_2':
                    {'body_4':'value_6',
                    'body_4':'value_35',
                    'body_5':'value_25',
                    'body_6':'value_25'},
                 'header_3':
                    {}}},

        'kvk_2':
            {'link_1':
                {'header_1':
                    {'body_1':'value_1', 
                    'body_2':'value_2',
                    'body_3':'value_3'},
                 'header_2':
                    {'body_4':'value_1',
                    'body_4':'value_3',
                    'body_5':'value_2'},
                'header_9':
                    {'body_10':'value_2'}
                    },
            'link_2':
                {'header_1':
                    {'body_2':'value_8',
                    'body_3':'value_9'},
                 'header_2':
                    {'body_6':'value_6',
                    'body_6':'value_35',
                    'body_5':'value_25',
                    'body_6':'value_25'},
                 'header_3':
                    {'body_9':'value_800'}},
             'link_3': {}},
        'kvk_3':
            {'link_1':
                {'header_10':{}}}}

#Write data

df = pd.DataFrame(columns = ['kvk', 'link'])
row = -1
for kvk, link_dict in data.items():    
    for link, header_dict in link_dict.items():
        row = row+1
        df.loc[row, 'kvk'] = kvk
        df.loc[row, 'link'] = link
        for header, body_dict in header_dict.items():

            for body, value in body_dict.items():
                df.loc[row, body] = value

哪个输出以下pandas数据帧:

     kvk    link   body_1   body_2   body_3    body_4    body_5   body_7  \
0  kvk_1  link_1  value_1  value_2  value_3   value_3   value_2      NaN   
1  kvk_1  link_2      NaN      NaN      NaN  value_35  value_25  value_8   
2  kvk_2  link_1  value_1  value_2  value_3   value_3   value_2      NaN   
3  kvk_2  link_2      NaN  value_8  value_9       NaN  value_25      NaN   
4  kvk_2  link_3      NaN      NaN      NaN       NaN       NaN      NaN   
5  kvk_3  link_1      NaN      NaN      NaN       NaN       NaN      NaN   

    body_8    body_6  body_10     body_9  
0      NaN       NaN      NaN        NaN  
1  value_9  value_25      NaN        NaN  
2      NaN       NaN  value_2        NaN  
3      NaN  value_25      NaN  value_800  
4      NaN       NaN      NaN        NaN  
5      NaN       NaN      NaN        NaN 

对于实际情况,这非常慢。我认为瓶颈是最后一行df.loc[row, body] = value,其中pandas需要根据dict键和递增的行号在不断增长的数据框中定位一个单元格。如果键指向的列存在,则添加新行并将值插入该行。如果该列不存在,则会创建一个新列并插入值。

我真的很喜欢这种设置,因为它允许我按名称查找列,这对于dict的设置非常理想。但是,正如我已经提到的,当数据帧超过大约10000行时,它停止运行。我该如何调整以加快速度?

谢谢

1 个答案:

答案 0 :(得分:4)

首先使用循环为字典列表更改数据的结构:

out = []
for k, v in data.items():
    for k1, v1 in v.items():
        d = {}
        for k2, v3 in v1.items():
            d.update(v3)
        out.append({**d, **{'kvk':k, 'link':k1}})
#print (out)

df = pd.DataFrame(out)
cols = ['kvk','link']
#if want cols for first columns in df and sorting body columns by numbers after _
c = cols + sorted(df.columns.difference(cols), key=lambda x: int(x.split('_')[1]))

#if need only change order by ['kvk','link']
#c = cols + df.columns.difference(cols).tolist()

df = df[c]
print (df)
     kvk    link   body_1   body_2   body_3    body_4    body_5    body_6  \
0  kvk_1  link_1  value_1  value_2  value_3   value_3   value_2       NaN   
1  kvk_1  link_2      NaN      NaN      NaN  value_35  value_25  value_25   
2  kvk_2  link_1  value_1  value_2  value_3   value_3   value_2       NaN   
3  kvk_2  link_2      NaN  value_8  value_9       NaN  value_25  value_25   
4  kvk_2  link_3      NaN      NaN      NaN       NaN       NaN       NaN   
5  kvk_3  link_1      NaN      NaN      NaN       NaN       NaN       NaN   

    body_7   body_8     body_9  body_10  
0      NaN      NaN        NaN      NaN  
1  value_8  value_9        NaN      NaN  
2      NaN      NaN        NaN  value_2  
3      NaN      NaN  value_800      NaN  
4      NaN      NaN        NaN      NaN  
5      NaN      NaN        NaN      NaN