如何将 Pandas DataFrame 转换为自定义嵌套 JSON?

How to convert Pandas DataFrame to custom nested JSON?

我是 Pandas 的新手,我正在尝试将 Pandas DataFrame 转换为自定义嵌套 JSON 字符串(可能将其写入文件)。我尝试使用内置的 Pandas to_json() 函数,但它对我来说不太管用。我正在 posting 我的 Pandas DF 的一部分以及我希望我的最终结果看起来像什么。理想情况下,我希望使用 DF 的索引填充 "id" 键。我认为我的目标是不用担心列名是什么,而是想办法以编程方式将 DF 转换为 JSON 字符串。我最初编写了一个 for 循环,它会遍历每一行并将内容写入文件,但经过一番思考后,我认为这很容易出错,因为大多数 JSON 序列化都是手动处理的。 任何帮助,将不胜感激。谢谢你,抱歉这么长 post。

Pandas 数据框

              BarcodeSequence LinkerPrimerSequence    BodySite    Year  Month   Day    Subject ReportedAntibioticUsage  DaysSinceExperimentStart                      Description
#SampleID
L1S8         AGCTGACTAGTC  GTGCCAGCMGCCGCGGTAA         gut  2008.0   10.0  28.0  subject-1                     Yes                       0.0         subject-1.gut.2008-10-28
L1S57        ACACACTATGGC  GTGCCAGCMGCCGCGGTAA         gut  2009.0    1.0  20.0  subject-1                      No                      84.0          subject-1.gut.2009-1-20
L1S76        ACTACGTGTGGT  GTGCCAGCMGCCGCGGTAA         gut  2009.0    2.0  17.0  subject-1                      No                     112.0          subject-1.gut.2009-2-17
L1S105       AGTGCGATGCGT  GTGCCAGCMGCCGCGGTAA         gut  2009.0    3.0  17.0  subject-1                      No                     140.0          subject-1.gut.2009-3-17
L2S155       ACGATGCGACCA  GTGCCAGCMGCCGCGGTAA   left palm  2009.0    1.0  20.0  subject-1                      No                      84.0    subject-1.left-palm.2009-1-20
L2S175       AGCTATCCACGA  GTGCCAGCMGCCGCGGTAA   left palm  2009.0    2.0  17.0  subject-1                      No                     112.0    subject-1.left-palm.2009-2-17
L2S204       ATGCAGCTCAGT  GTGCCAGCMGCCGCGGTAA   left palm  2009.0    3.0  17.0  subject-1                      No                     140.0    subject-1.left-palm.2009-3-17
L2S222       CACGTGACATGT  GTGCCAGCMGCCGCGGTAA   left palm  2009.0    4.0  14.0  subject-1                      No                     168.0    subject-1.left-palm.2009-4-14
L3S242       ACAGTTGCGCGA  GTGCCAGCMGCCGCGGTAA  right palm  2008.0   10.0  28.0  subject-1                     Yes                       0.0  subject-1.right-palm.2008-10-28
L3S294       CACGACAGGCTA  GTGCCAGCMGCCGCGGTAA  right palm  2009.0    

预期 JSON 字符串

[
{
  "id": "L1S8",
  "metadata": {
    "BarcodeSequence": "AGCTGACTAGTC",
    "LinkerPrimerSequence": "GTGCCAGCMGCCGCGGTAA",
    "BodySite": "gut",
    "Year": 2008.0,
    "Month": 10.0,
    "Day": 28.0,
    "Subject": "subject-1",
    "ReportedAntibioticUsage": "Yes",
    "DaysSinceExperimentStart": 0.0,
    "Description": "subject-1.gut.2008-10-28"
  },
  "sample_frequency": "7068.0"
},
{
  "id": "L1S57",
  "metadata": {
    "BarcodeSequence": "ACACACTATGGC",
    "LinkerPrimerSequence": "GTGCCAGCMGCCGCGGTAA",
    "BodySite": "gut",
    "Year": 2009.0,
    "Month": 1.0,
    "Day": 20.0,
    "Subject": "subject-1",
    "ReportedAntibioticUsage": "No",
    "DaysSinceExperimentStart": 84.0,
    "Description": "subject-1.gut.2009-1-20"
  },
  "sample_frequency": "8756.0"
},
{
  "id": "L1S76",
  "metadata": {
    "BarcodeSequence": "ACTACGTGTGGT",
    "LinkerPrimerSequence": "GTGCCAGCMGCCGCGGTAA",
    "BodySite": "gut",
    "Year": 2009.0,
    "Month": 2.0,
    "Day": 17.0,
    "Subject": "subject-1",
    "ReportedAntibioticUsage": "No",
    "DaysSinceExperimentStart": 112.0,
    "Description": "subject-1.gut.2009-2-17"
  },
  "sample_frequency": "7922.0"
},
{
  "id": "L1S105",
  "metadata": {
    "BarcodeSequence": "AGTGCGATGCGT",
    "LinkerPrimerSequence": "GTGCCAGCMGCCGCGGTAA",
    "BodySite": "gut",
    "Year": 2009.0,
    "Month": 3.0,
    "Day": 17.0,
    "Subject": "subject-1",
    "ReportedAntibioticUsage": "No",
    "DaysSinceExperimentStart": 140.0,
    "Description": "subject-1.gut.2009-3-17"
  },
  "sample_frequency": "7865.0"
}
]

这是一种动态构建 JSON(某种程度上)的方法。不过,您仍然需要做出一些假设,我不确定您的用例是否会接受这些假设:

  1. 列名称是唯一的。
  2. 您知道要用作 "value" 列的列的名称。在我的示例数据框中,我将其称为 valuesample_frequency 将是示例数据框中的 "value" 列。
  3. 您将使用数据帧索引作为 ìd 参数。这可能会或可能不会被接受。可能您也需要提前识别此列,在这种情况下,您应该使用 .set_index().
  4. 将其设置为数据帧索引

话虽如此:

import pandas as pd
import numpy as np
import json

data = pd.DataFrame(
    {
        'meta_1': np.random.choice(['A', 'B', 'C'], 10),
        'meta_2': np.random.choice(['Blue', 'Green', 'Red'], 10),
        'value': np.random.rand(10)
    }
)

print(data)

这是数据:

    meta_1 meta_2     value
0      A    Red  0.095142
1      C    Red  0.855082
2      C   Blue  0.619704
3      B  Green  0.371495
4      A    Red  0.000771
5      B  Green  0.027218
6      B   Blue  0.655847
7      B   Blue  0.657976
8      A  Green  0.060862
9      C    Red  0.702788

现在将要使用的列设置为 "value" 列。

val_col_name = 'value'

然后是带有嵌套字典理解的列表理解:

json.dumps([{'id': i, 'metadata': {j: row[j] for j in data.columns if j != val_col_name}, val_col_name: row[val_col_name]} for i, row in data.iterrows()])

给出:

[{"id": 0, "metadata": {"meta_1": "B", "meta_2": "Red"}, "value": 0.3169439789955154}, {"id": 1, "metadata": {"meta_1": "C", "meta_2": "Green"}, "value": 0.5672345948633107}, {"id": 2, "metadata": {"meta_1": "B", "meta_2": "Red"}, "value": 0.36909249143056766}, {"id": 3, "metadata": {"meta_1": "C", "meta_2": "Red"}, "value": 0.8033913639248945}, {"id": 4, "metadata": {"meta_1": "B", "meta_2": "Red"}, "value": 0.04500655943447107}, {"id": 5, "metadata": {"meta_1": "A", "meta_2": "Red"}, "value": 0.43388699497426875}, {"id": 6, "metadata": {"meta_1": "C", "meta_2": "Green"}, "value": 0.14265358049247878}, {"id": 7, "metadata": {"meta_1": "C", "meta_2": "Red"}, "value": 0.7823049064345722}, {"id": 8, "metadata": {"meta_1": "B", "meta_2": "Blue"}, "value": 0.9522025604707016}, {"id": 9, "metadata": {"meta_1": "C", "meta_2": "Red"}, "value": 0.3863207799791931}]