从列中的字典中提取值作为列值,NA 存在

Extract value from dict in column as column value, with NA's present

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

因为有 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}}

字典 d 的长度在 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 列在变化。

一个选项是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
  • 使用来自
  • 的解决方案
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