0

我目前正在尝试从出现在一系列列中的几个 dicts 中提取值,有两个问题:

由于有 4 列有问题,因此它们是通过以下代码行从先前的 dict-in-column 值中解压缩的:

df = pd.concat([df.drop(['ids'], axis = 1), df['ids'].apply(pd.Series)], axis = 1)

这个字典是在以下形式的列中解压缩一个字典:

d = {'a': {'id': 12}, 'b': {'id': 13}, 'c': {'id': 14}, 'd': {'id': 15}}

dictd的长度在 0-4 之间。

在解压数据框之前,我解压的列如下所示:

       ids
406    {'a': {'id': '12'}}
408    None
409    {'a': {'id': '21'}, 'b': {'id': '23'}}
417    {'a': {'id': '53'}, 'b': {'id': '98'}, 'c': {'id': '45'}}
419    None 

解压后它现在有形式

        a                        b                         c
408     None                     {'id': '12'}       None
409     {'id': '32'}             {'id': '45'}       {'id': '36'}
417     {'id': '09'}             {'id': '31'}       None

虽然这最初解决了我的第一个问题,但我现在正试图将值从包含字典的列中提取出来,对此我有点不知所措。

我尝试过的潜在解决方案只是为每一列(a、b、c)运行上面的代码段,但这既丑陋又低效。至多我知道,pd.json_normalize当我第一次启动我的程序时,一个简单的修复方法是对初始数据帧进行修复,但是对于似乎可以轻松解决的问题,这将需要进行重大修复和重构。作为参考,理想的输出是这样的:

        a                        b                  c
408     None                     12                 None
409     32                       45                 36
417     09                       31                 None

整个数据框有几十万行,有 20 列在不断变化。

4

2 回答 2

1

一种选择是为apply每一列添加一个客户函数

def my_func(val):
    if isinstance(val,dict):
        return val['id']
    else:
        return val

for col in df.columns:
    df[col]=df[col].apply(my_func)

    a       b   c
0   None    12  None
1   32      45  36
2   09      31  None
于 2020-09-23T16:45:16.627 回答
1
import pandas as pd

# setup dataframe
data = {'ids': [{'a': {'id': '12'}}, None, {'a': {'id': '21'}, 'b': {'id': '23'}}, {'a': {'id': '53'}, 'b': {'id': '98'}, 'c': {'id': '45'}}, None]}
df = pd.DataFrame(data)

# display(df)
                                                         ids
0                                        {'a': {'id': '12'}}
1                                                       None
2                     {'a': {'id': '21'}, 'b': {'id': '23'}}
3  {'a': {'id': '53'}, 'b': {'id': '98'}, 'c': {'id': '45'}}
4                                                       None

# fill None with {}
df.ids = df.ids.fillna({i: {} for i in df.index})

# normalize the column
df = pd.json_normalize(df.ids).dropna(how='all')

# display(df)
  a.id b.id c.id
0   12  NaN  NaN
2   21   23  NaN
3   53   98   45
于 2020-09-23T16:51:59.613 回答