用正确的 Dtype 将带有无意义键的 json 读入 pandas data.frame

Posted

技术标签:

【中文标题】用正确的 Dtype 将带有无意义键的 json 读入 pandas data.frame【英文标题】:Read json with meaningless keys into pandas data.frame with correct Dtype 【发布时间】:2022-01-13 17:34:34 【问题描述】:

在一个项目中,我收到需要读入 pandas data.frame 的 json。

格式如下所示(列和行更多):

    "a;b;c;d":
      "1":"100;14/09/2020;0.5;XK3",
      "2":"NA;17/09/2020;0.95;NA",
      "3":"102;NA;NA;KZ2"

我可以拆分字符串,但我的类型不是我想要的。有没有自动转换u 中的列的方法?

from io import StringIO
import pandas as pd

TESTDATA = StringIO("""
        "a;b;c;d":
          "1":"100;14/09/2020;0.5;XK3",
          "2":"NA;17/09/2020;0.95;NA",
          "3":"102;NA;NA;KZ2"
          """)

df = pd.read_json(TESTDATA)
df.head(10)
vnames = df.columns[0].split(';')

u = (df[df.columns[0]].str.split(';', expand=True)
             .set_axis(vnames, axis=1, inplace=False)).convert_dtypes()

print(u.head(10))

print(u.info())

我希望 Dtype 为 int64, datetime64, float64, str

【问题讨论】:

你的真实数据有相同的形式吗?一个单键的字典? @Corralien,是的,我的真实数据具有相同的形式。文件中有多个文件,文件中的列也比较多,但总体上是一样的。 你的 json 有什么“不正确”的地方? @balmy,json格式有效,但键值对无意义。这是一个以可怕的方式嵌入到 json 中的表格。 所以它是“正确的”JSON,但不是你想要的。请编辑您的问题标题以更正此问题。 【参考方案1】:

您可以执行以下操作:

from io import StringIO
import pandas as pd
import numpy as np 

TESTDATA = StringIO("""
        "a;b;c;d":
          "1":"100;14/09/2020;0.5;XK3",
          "2":"NA;17/09/2020;0.95;NA",
          "3":"102;NA;NA;KZ2"
          """)

df = pd.read_json(TESTDATA)




df.head(10)
vnames = df.columns[0].split(';')

u = (df[df.columns[0]].str.split(';', expand=True)
             .set_axis(vnames, axis=1, inplace=False))



u = u.apply(lambda x: x.str.strip()).replace('NA', np.nan)

u = u.to_json()
u = pd.read_json(u).convert_dtypes()

print(u.head(10))

print(u.info())

【讨论】:

它将日期保留为字符串,但它或多或少是我想要的。因此,如果我在接下来的几天内没有得到可以满足日期要求的答案,我会接受这个答案,因为它是一项重大改进。【参考方案2】:

在创建 DataFrame 之前尝试显式类型转换字符串值,如下例所示:

import json
import pandas as pd

s_src = '''    "a;b;c;d":
      "1":"100;14/09/2020;0.5;XK3",
      "2":"NA;17/09/2020;0.95;NA",
      "3":"102;NA;NA;KZ2"'''

s = json.loads(s_src)

# per-column type conversion
typeconv = [int, pd.to_datetime, float, str]

for k1, subd in s.items():
    cols = k1.split(';')
    rows = []
    for k, v in subd.items():
        row = v.split(';')
        conv_row =[]
        for cvt, r in zip(typeconv, row):
            # screen for missing values
            if r == 'NA':
                conv_row.append(None)
            else:
                # apply the conversion function for this column
                conv_row.append(cvt(r))
        rows.append(conv_row)

df = pd.DataFrame(rows, columns=cols)

【讨论】:

我的目标是避免手动类型转换(硬编码)值。否则,我可以使用类似numericCols = ["c"] \\ u[numericCols] = u[numericCols].apply(pd.to_numeric,errors='coerce')

以上是关于用正确的 Dtype 将带有无意义键的 json 读入 pandas data.frame的主要内容,如果未能解决你的问题,请参考以下文章

Django 将带有外键的查询集转换为 JSON

将数组内容正确存储到带有键的字典中

使用 Jackson 序列化带有排序键的 JSON

两个带有json键的数组[重复]

使用 TypeScript 对带有前缀的 JSON 文件键的类型定义

带有对象和键的 UIPicker 使用 JSON