如何使用 NaN 对列进行 json_normalize

Tre*_*ney 5 python json dictionary pandas json-normalize

  • 这个问题特定于a中的数据列pandas.DataFrame
  • 此问题取决于列中的值是否为strdictlisttype。
  • 这个问题解决了在不是有效选项NaN时处理值的问题。df.dropna().reset_index(drop=True)

情况1

  • 对于类型的列,在使用 之前,str必须将列中的值转换为dict类型,使用, 。ast.literal_eval.json_normalize
import numpy as np
import pandas as pd
from ast import literal_eval

df = pd.DataFrame({'col_str': ['{"a": "46", "b": "3", "c": "12"}', '{"b": "2", "c": "7"}', '{"c": "11"}', np.NaN]})

                            col_str
0  {"a": "46", "b": "3", "c": "12"}
1              {"b": "2", "c": "7"}
2                       {"c": "11"}
3                               NaN

type(df.iloc[0, 0])
[out]: str

df.col_str.apply(literal_eval)
Run Code Online (Sandbox Code Playgroud)

错误:

df.col_str.apply(literal_eval) results in ValueError: malformed node or string: nan
Run Code Online (Sandbox Code Playgroud)

案例2

  • 对于类型的列dict,用于pandas.json_normalize将键转换为列标题,将值转换为行
df = pd.DataFrame({'col_dict': [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}, {"c": "11"}, np.NaN]})

                           col_dict
0  {'a': '46', 'b': '3', 'c': '12'}
1              {'b': '2', 'c': '7'}
2                       {'c': '11'}
3                               NaN

type(df.iloc[0, 0])
[out]: dict

pd.json_normalize(df.col_dict)
Run Code Online (Sandbox Code Playgroud)

错误:

pd.json_normalize(df.col_dict) results in AttributeError: 'float' object has no attribute 'items'
Run Code Online (Sandbox Code Playgroud)

案例3

  • 在类型列中str,内部有dict一个list.
  • 标准化列
    • apply literal_eval,因为爆炸不适用于str类型
    • 分解列以dicts将行分开
    • 标准化列
df = pd.DataFrame({'col_str': ['[{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]', '[{"b": "2", "c": "7"}, {"c": "11"}]', np.nan]})

                                                    col_str
0  [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]
1                       [{"b": "2", "c": "7"}, {"c": "11"}]
2                                                       NaN

type(df.iloc[0, 0])
[out]: str
    
df.col_str.apply(literal_eval)
Run Code Online (Sandbox Code Playgroud)

错误:

df.col_str.apply(literal_eval) results in ValueError: malformed node or string: nan
Run Code Online (Sandbox Code Playgroud)

Tre*_*ney 12

  • 始终可以选择:
    • df = df.dropna().reset_index(drop=True)
    • 这对于这里的虚拟数据来说很好,或者在处理其他列无关紧要的数据帧时。
    • 对于需要额外列的数据框来说,这不是一个很好的选择。
  • 测试于python 3.10,pandas 1.4.3

情况1

  • 由于该列包含str类型,因此用'{}'(a str)填充
import numpy as np
import pandas as pd
from ast import literal_eval

df = pd.DataFrame({'col_str': ['{"a": "46", "b": "3", "c": "12"}', '{"b": "2", "c": "7"}', '{"c": "11"}', np.NaN]})

                            col_str
0  {"a": "46", "b": "3", "c": "12"}
1              {"b": "2", "c": "7"}
2                       {"c": "11"}
3                               NaN

type(df.iloc[0, 0])
[out]: str

# fillna
df.col_str = df.col_str.fillna('{}')

# convert the column to dicts
df.col_str = df.col_str.apply(literal_eval)

# use json_normalize
df = df.join(pd.json_normalize(df.pop('col_str')))

# display(df)
     a    b    c
0   46    3   12
1  NaN    2    7
2  NaN  NaN   11
3  NaN  NaN  NaN
Run Code Online (Sandbox Code Playgroud)

案例2

至少pandas 1.3.4pd.json_normalize(df.col_dict)至少对于这个简单的例子来说,工作没有问题。


  • 由于该列包含dict类型,因此用{}(而不是str)填充
  • 这需要使用字典理解来填充,因为fillna({})不起作用
df = pd.DataFrame({'col_dict': [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}, {"c": "11"}, np.NaN]})

                           col_dict
0  {'a': '46', 'b': '3', 'c': '12'}
1              {'b': '2', 'c': '7'}
2                       {'c': '11'}
3                               NaN

type(df.iloc[0, 0])
[out]: dict
    
# fillna
df.col_dict = df.col_dict.fillna({i: {} for i in df.index})

# use json_normalize
df = df.join(pd.json_normalize(df.pop('col_dict')))

# display(df)
     a    b    c
0   46    3   12
1  NaN    2    7
2  NaN  NaN   11
3  NaN  NaN  NaN
Run Code Online (Sandbox Code Playgroud)

案例3

  1. 填写( NaNsa )'[]'str
  2. 现在literal_eval可以工作了
  3. .explode可以在列上使用,将dict值分隔到行中
  4. 现在NaNs需要填写{}(不是str
  5. 然后可以对列进行归一化
  • lists对于列属于dicts非类型的情况str,请跳至.explode
df = pd.DataFrame({'col_str': ['[{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]', '[{"b": "2", "c": "7"}, {"c": "11"}]', np.nan]})

                                                    col_str
0  [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]
1                       [{"b": "2", "c": "7"}, {"c": "11"}]
2                                                       NaN

type(df.iloc[0, 0])
[out]: str
    
# fillna
df.col_str = df.col_str.fillna('[]')

# literal_eval
df.col_str = df.col_str.apply(literal_eval)

# explode
df = df.explode('col_str', ignore_index=True)

# fillna again
df.col_str = df.col_str.fillna({i: {} for i in df.index})

# use json_normalize
df = df.join(pd.json_normalize(df.pop('col_str')))

# display(df)
     a    b    c
0   46    3   12
1  NaN    2    7
2  NaN    2    7
3  NaN  NaN   11
4  NaN  NaN  NaN
Run Code Online (Sandbox Code Playgroud)