Python Pandas(6):Pandas JSON

发布于:2025-02-11 ⋅ 阅读:(139) ⋅ 点赞:(0)

        JSON(JavaScript Object Notation,JavaScript 对象表示法),是存储和交换文本信息的语法,类似 XML。JSON 比 XML 更小、更快,更易解析。Pandas 提供了强大的方法来处理 JSON 格式的数据,支持从 JSON 文件或字符串中读取数据并将其转换为 DataFrame,以及将 DataFrame 转换回 JSON 格式。

操作 方法 说明
从 JSON 文件/字符串读取数据 pd.read_json() 从 JSON 数据中读取并加载为 DataFrame
将 DataFrame 转换为 JSON DataFrame.to_json() 将 DataFrame 转换为 JSON 格式的数据,可以指定结构化方式
支持 JSON 结构化方式 orient 参数 支持多种结构化方式,如 splitrecordscolumns

        Pandas 可以很方便的处理 JSON 数据,本文以 sites.json 为例,内容如下:

[
  {
    "id": "A001",
    "name": "bing",
    "url": "www.bing.com",
    "likes": 61
  },
  {
    "id": "A002",
    "name": "Google",
    "url": "www.google.com",
    "likes": 124
  },
  {
    "id": "A003",
    "name": "淘宝",
    "url": "www.taobao.com",
    "likes": 45
  }
]

1 从 JSON 文件/字符串加载数据

1.1 pd.read_json() - 读取 JSON 数据

        read_json() 用于从 JSON 格式的数据中读取并加载为一个 DataFrame。它支持从 JSON 文件、JSON 字符串或 JSON 网址中加载数据。

df = pd.read_json(
    path_or_buffer,      # JSON 文件路径、JSON 字符串或 URL
    orient=None,         # JSON 数据的结构方式,默认是 'columns'
    dtype=None,          # 强制指定列的数据类型
    convert_axes=True,   # 是否转换行列索引
    convert_dates=True,  # 是否将日期解析为日期类型
    keep_default_na=True # 是否保留默认的缺失值标记
)
参数 说明 默认值
path_or_buffer JSON 文件的路径、JSON 字符串或 URL 必需参数
orient 定义 JSON 数据的格式方式。常见值有 splitrecordsindexcolumnsvalues None(根据文件自动推断)
dtype 强制指定列的数据类型 None
convert_axes 是否将轴转换为合适的数据类型 True
convert_dates 是否将日期解析为日期类型 True
keep_default_na 是否保留默认的缺失值标记(如 NaN True

        常见的 orient 参数选项:

orient 值 JSON 格式示例 描述
split {"index":["a","b"],"columns":["A","B"],"data":[[1,2],[3,4]]} 使用键 indexcolumns 和 data 结构
records [{"A":1,"B":2},{"A":3,"B":4}] 每个记录是一个字典,表示一行数据
index {"a":{"A":1,"B":2},"b":{"A":3,"B":4}} 使用索引为键,值为字典的方式
columns {"A":{"a":1,"b":3},"B":{"a":2,"b":4}} 使用列名为键,值为字典的方式
values [[1,2],[3,4]] 只返回数据,不包括索引和列名

        从 JSON 文件加载数据,to_string() 用于返回 DataFrame 类型的数据,我们也可以直接处理 JSON 字符串。

import pandas as pd

df = pd.read_json('sites.json')

print(df.to_string())

        JSON 对象与 Python 字典具有相同的格式,所以我们可以直接将 Python 字典转化为 DataFrame 数据:

import pandas as pd

# 字典格式的 JSON
s = {
    "col1": {"row1": 1, "row2": 2, "row3": 3},
    "col2": {"row1": "x", "row2": "y", "row3": "z"}
}

# 读取 JSON 转为 DataFrame
df = pd.DataFrame(s)
print(df)

        从 JSON 字符串加载数据:

from io import StringIO

import pandas as pd

# JSON 字符串
json_data = '''
[
  {"Name": "Alice", "Age": 25, "City": "New York"},
  {"Name": "Bob", "Age": 30, "City": "Los Angeles"},
  {"Name": "Charlie", "Age": 35, "City": "Chicago"}
]
'''

# 从 JSON 字符串读取数据
df = pd.read_json(StringIO(json_data))

print(df)

1.2 内嵌的 JSON 数据

        假设有一组内嵌的 JSON 数据文件 nested_list.json :

{
    "school_name": "ABC primary school",
    "class": "Year 1",
    "students": [
    {
        "id": "A001",
        "name": "Tom",
        "math": 60,
        "physics": 66,
        "chemistry": 61
    },
    {
        "id": "A002",
        "name": "James",
        "math": 89,
        "physics": 76,
        "chemistry": 51
    },
    {
        "id": "A003",
        "name": "Jenny",
        "math": 79,
        "physics": 90,
        "chemistry": 78
    }]
}

        使用以下代码格式化完整内容:

import pandas as pd

df = pd.read_json('nested_list.json')

print(df)

        这时我们就需要使用到 json_normalize() 方法将内嵌的数据完整的解析出来:

import pandas as pd
import json

# 使用 Python JSON 模块载入数据
with open('nested_list.json', 'r') as f:
    data = json.loads(f.read())

# 展平数据
df_nested_list = pd.json_normalize(data, record_path=['students'])
print(df_nested_list)

        data = json.loads(f.read()) 使用 Python JSON 模块载入数据。json_normalize() 使用了参数 record_path 并设置为 ['students'] 用于展开内嵌的 JSON 数据 students。显示结果还没有包含 school_name 和 class 元素,如果需要展示出来可以使用 meta 参数来显示这些元数据:

import pandas as pd
import json

# 使用 Python JSON 模块载入数据
with open('nested_list.json', 'r') as f:
    data = json.loads(f.read())

# 展平数据
df_nested_list = pd.json_normalize(
    data,
    record_path=['students'],
    meta=['school_name', 'class']
)
print(df_nested_list)

        接下来尝试读取更复杂的 JSON 数据,该数据嵌套了列表和字典,数据文件 nested_mix.json 如下:

{
  "school_name": "local primary school",
  "class": "Year 1",
  "info": {
    "president": "John Kasich",
    "address": "ABC road, London, UK",
    "contacts": {
      "email": "admin@e.com",
      "tel": "123456789"
    }
  },
  "students": [
    {
      "id": "A001",
      "name": "Tom",
      "math": 60,
      "physics": 66,
      "chemistry": 61
    },
    {
      "id": "A002",
      "name": "James",
      "math": 89,
      "physics": 76,
      "chemistry": 51
    },
    {
      "id": "A003",
      "name": "Jenny",
      "math": 79,
      "physics": 90,
      "chemistry": 78
    }
  ]
}

        nested_mix.json 文件转换为 DataFrame:

import pandas as pd
import json

# 使用 Python JSON 模块载入数据
with open('nested_mix.json', 'r') as f:
    data = json.loads(f.read())

df = pd.json_normalize(
    data,
    record_path=['students'],
    meta=[
        'class',
        ['info', 'president'],
        ['info', 'contacts', 'tel']
    ]
)

print(df)

1.3 读取内嵌数据中的一组数据

        以下是实例文件 nested_deep.json,我们只读取内嵌中的 math 字段:

{
  "school_name": "local primary school",
  "class": "Year 1",
  "students": [
    {
      "id": "A001",
      "name": "Tom",
      "grade": {
        "math": 60,
        "physics": 66,
        "chemistry": 61
      }
    },
    {
      "id": "A002",
      "name": "James",
      "grade": {
        "math": 89,
        "physics": 76,
        "chemistry": 51
      }
    },
    {
      "id": "A003",
      "name": "Jenny",
      "grade": {
        "math": 79,
        "physics": 90,
        "chemistry": 78
      }
    }
  ]
}

        这里我们需要使用到 glom 模块来处理数据套嵌,glom 模块允许我们使用 . 来访问内嵌对象的属性。第一次使用我们需要安装 glom:

pip3 install glom
import pandas as pd
from glom import glom

df = pd.read_json('nested_deep.json')

data = df['students'].apply(lambda row: glom(row, 'grade.math'))
print(data)

2 将 DataFrame 转换为 JSON

2.1 DataFrame.to_json() - 将 DataFrame 转换为 JSON 数据

        to_json() 方法用于将 DataFrame 转换为 JSON 格式的数据,可以指定 JSON 的结构化方式。语法格式:

df.to_json(
    path_or_buffer=None,    # 输出的文件路径或文件对象,如果是 None 则返回 JSON 字符串
    orient=None,            # JSON 格式方式,支持 'split', 'records', 'index', 'columns', 'values'
    date_format=None,       # 日期格式,支持 'epoch', 'iso'
    default_handler=None,   # 自定义非标准类型的处理函数
    lines=False,            # 是否将每行数据作为一行(适用于 'records' 或 'split')
    encoding='utf-8'        # 编码格式
)
参数 说明 默认值
path_or_buffer 输出的文件路径或文件对象,若为 None,则返回 JSON 字符串 None
orient 指定 JSON 格式结构,支持 splitrecordsindexcolumnsvalues None(默认是 columns
date_format 日期格式,支持 'epoch' 或 'iso' 格式 None
default_handler 自定义处理非标准类型(如 datetime 等)的处理函数 None
lines 是否将每行数据作为一行输出(适用于 records 或 split False
encoding 输出文件的编码格式 'utf-8'
import pandas as pd

# 创建 DataFrame
df = pd.DataFrame({
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, 30, 35],
    'City': ['New York', 'Los Angeles', 'Chicago']
})

# 将 DataFrame 转换为 JSON 字符串
json_str = df.to_json()

print(json_str)

        将 DataFrame 转换为 JSON 文件(指定 orient='records'):

import pandas as pd

# 创建 DataFrame
df = pd.DataFrame({
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, 30, 35],
    'City': ['New York', 'Los Angeles', 'Chicago']
})

# 将 DataFrame 转换为 JSON 文件,指定 orient='records'
df.to_json('data.json', orient='records', lines=True)

        将 DataFrame 转换为 JSON 并指定日期格式:

import pandas as pd

# 创建 DataFrame,包含日期数据
df = pd.DataFrame({
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Date': pd.to_datetime(['2021-01-01', '2022-02-01', '2023-03-01']),
    'Age': [25, 30, 35]
})

# 将 DataFrame 转换为 JSON,并指定日期格式为 'iso'
json_str = df.to_json(date_format='iso')

print(json_str)


网站公告

今日签到

点亮在社区的每一天
去签到