Pandas read_json 函数允许您读取 JSON 文件并将其转换为Pandas数据框。
在本教程中,您将学习如何使用 Python 的 Pandas 加载 JSON 文件、处理各种 JSON 格式、自定义列标签、推断数据类型、解析日期等read_json
功能。
JSON 结构和语法
在我们深入研究 Pandas 之前read_json()
函数,我们简单回顾一下其结构和语法JSON.
[
{
"name": "John",
"age": 44,
"city": "New York"
},
{
"name": "Alice",
"age": 25,
"city": "San Francisco"
}
]
它由键值对组成,支持各种数据类型,例如字符串、数字、布尔值、数组和对象。
什么是 Pandas read_json?
The read_json()
Pandas 中的函数使您能够将 JSON 数据加载到数据框.
它提供了灵活的选项来处理各种 JSON 格式,包括嵌套结构、不同方向和数据类型。
通过使用read_json()
,您可以轻松地将 JSON 字符串、本地文件或 URL 转换为结构化 DataFrame,以进行进一步的数据分析和操作。
读取 JSON 文件
要开始读取 JSON 文件,您只需提供文件路径即可read_json()
功能。
让我们考虑一个示例,其中有一个名为“data.json”的 JSON 文件,其中包含以下内容:
[
{
"name": "John",
"age": 44,
"city": "New York"
},
{
"name": "Alice",
"age": 25,
"city": "San Francisco"
}
]
现在,让我们使用以下命令将此 JSON 文件加载到 DataFrame 中read_json
功能:
import pandas as pd
df = pd.read_json('data.json')
print(df)
Output:
name age city
0 John 44 New York
1 Alice 25 San Francisco
生成的数据框,df
,包含从文件加载的 JSON 数据。然后我们打印 DataFrame 以查看输出。
从 URL 或 API 读取 JSON
除了从本地文件读取 JSON 之外,Pandas 的read_json()
函数还允许您直接从 URL 或 API 端点读取 JSON 数据。
当您想要从 Web 检索 JSON 数据并将其加载到 DataFrame 中时,这非常有用。
让我们考虑一个示例,其中我们有一个返回以下 JSON 数据的 URL:
{
"name": "John",
"age": 44,
"city": "New York"
}
要从 URL 读取此 JSON 数据,您可以使用read_json()
函数如下:
import pandas as pd
url = 'https://example.com/data.json'
df = pd.read_json(url)
print(df)
Output:
name age city
0 John 44 New York
在上面的代码中,我们指定 JSON 数据的 URL 并将其传递给read_json()
功能。
该函数从 URL 检索 JSON 数据并将其加载到 DataFrame 中。最后,我们打印 DataFrame 以查看输出。
读取压缩的 JSON
有时,JSON 数据会被压缩以减小文件大小或优化数据传输。
Pandas read_json()
函数支持直接读取压缩的JSON文件,无需手动解压。
假设我们有一个名为“data.json.gz”的压缩 JSON 文件,其中包含以下内容:
[
{
"name": "John",
"age": 44,
"city": "New York"
},
{
"name": "Alice",
"age": 25,
"city": "San Francisco"
}
]
要读取这个压缩的 JSON 文件,您可以使用read_json()
函数与compression
参数设置为适当的压缩方法。
对于 gzip 压缩的文件,我们设置compression='gzip'
:
import pandas as pd
df = pd.read_json('data.json.gz', compression='gzip')
print(df)
Output:
name age city
0 John 44 New York
1 Alice 25 San Francisco
在上面的代码中,我们将压缩的 JSON 文件“data.json.gz”的文件路径传递给read_json()
功能。
然后,我们指定compression='gzip'
指示该文件是 gzip 压缩的。该函数自动处理解压缩并将 JSON 数据加载到 DataFrame 中。
通过指定压缩参数,read_json
函数可以检测和处理不同的压缩格式,例如 gzip、zip、bz2 等。
此功能无需手动解压缩,并简化了读取压缩 JSON 文件的过程。
读取嵌套的 JSON
JSON 数据通常包含嵌套结构,例如对象或对象内的数组。
让我们考虑一个示例,其中有以下嵌套 JSON 数据:
{
"name": "John",
"age": 44,
"address": {
"city": "New York",
"country": "USA"
}
}
要读取这个嵌套的 JSON 数据,我们可以使用read_json()
函数如下:
import json
with open('nested_sample.json') as f:
data = json.load(f)
df = pd.json_normalize(data)
print(df)
Output:
name age address.city address.country
0 John 44 New York USA
在此示例中,我们使用以下方式加载数据json.load
,然后我们用json_normalize
展平嵌套的 JSON。
嵌套 JSON 的另一个示例,其中 JSON 键包含 Python 字典:
{
"employees": [
{ "firstName": "John", "lastName": "Doe" },
{ "firstName": "Adam", "lastName": "Smith" },
{ "firstName": "Peter", "lastName": "Jones" }
]
}
您可以使用以下方法处理原始结构json_normalize
Pandas 的函数,如下所示:
import json
import pandas as pd
with open('sample.json') as f:
data = json.load(f)
df = pd.json_normalize(data,'employees')
print(df)
Output:
firstName lastName
0 John Doe
1 Adam Smith
2 Peter Jones
The json_normalize
函数用于扁平化数据结构,并将嵌套字典转换为具有单独列“firstName”和“lastName”的 DataFrame。
自定义列名称
默认情况下,Pandas 的read_json()
函数使用 JSON 对象中的键作为生成的 DataFrame 中的列名称。
但是,您可以通过重命名 DataFrame 的列来自定义列名称。
让我们考虑一个示例,其中有以下 JSON 数据:
{
"firstname": "John",
"lastname": "Doe",
"age": 44
}
代码如下所示:
import pandas as pd
df = pd.read_json('sample.json')
df.columns = ['First Name', 'Last Name', 'Age']
print(df)
Output:
First Name Last Name Age
0 John Doe 44
了解方向
The read_json()
Pandas 中的函数提供了解释不同 JSON 数据结构的各种方向。
The orient
参数允许您指定所需的方向。让我们探讨一下可用的方向及其用例:
split
The 'split'
orientation 将 JSON 数据解释为列表字典,其中每个列表对应于生成的 DataFrame 中的一列。
考虑以下 JSON 数据:
{
"name": ["John", "Alice"],
"age": [44, 25],
"city": ["New York", "San Francisco"]
}
要读取此 JSON 数据,请使用'split'
方向,我们可以使用read_json()
函数如下:
import pandas as pd
df = pd.read_json('data.json', orient='split')
print(df)
Output:
name age city
0 John 44 New York
1 Alice 25 San Francisco
records
The 'records'
方向将 JSON 数据中的每个元素解释为单独的记录,由字典表示。
考虑文件中的以下 JSON 数据:
[
{"name": "John", "age": 44},
{"name": "Alice", "age": 25}
]
要读取此 JSON 数据,请使用'records'
方向,我们可以使用read_json()
函数如下:
import pandas as pd
df = pd.read_json('data.json', orient='records')
print(df)
Output:
name age
0 John 44
1 Alice 25
index
The 'index'
orientation 将 JSON 数据视为字典的字典,其中外部字典键对应于行标签,内部字典键对应于列名称。
考虑以下 JSON 数据:
{
"row1": {"name": "John", "age": 44},
"row2": {"name": "Alice", "age": 25}
}
要读取此 JSON 数据,请使用'index'
方向,我们可以使用read_json()
函数如下:
import pandas as pd
df = pd.read_json('data.json', orient='index')
print(df)
Output:
name age
row1 John 44
row2 Alice 25
columns
The 'columns'
orientation 将 JSON 数据视为字典的字典,其中外部字典键这次对应于列名称,内部字典键对应于行标签。
考虑以下 JSON 数据:
{
"name": {"row1": "John", "row2": "Alice"},
"age": {"row1": 44, "row2": 25}
}
要读取此 JSON 数据,请使用'columns'
方向,我们可以使用read_json()
函数如下:
import pandas as pd
df = pd.read_json('data.json', orient='columns')
print(df)
Output:
name age
row1 John 44
row2 Alice 25
values
The 'values'
orientation 将 JSON 数据视为列表的列表,其中每个列表代表 DataFrame 中的一行。
考虑以下 JSON 数据:
[
["John", 44],
["Alice", 25]
]
要读取此 JSON 数据,请使用'values'
方向,我们可以使用read_json()
函数如下:
import pandas as pd
df = pd.read_json('data.json', orient='values')
print(df)
Output:
name age
0 John 44
1 Alice 25
数据类型
默认情况下,Pandas 的read_json()
函数根据 JSON 数据推断列的数据类型。但是,您可以使用以下命令控制数据类型dtype
范围。
让我们考虑一个示例,其中有以下 JSON 数据:
[
{
"name": "John",
"age": "44",
"city": "New York"
},
{
"name": "Alice",
"age": "25",
"city": "San Francisco"
}
]
要读取此 JSON 数据并指定列的数据类型,我们可以使用read_json()
函数如下:
import pandas as pd
newtypes = {"name": str, "age": int, "city": str}
df = pd.read_json('data.json', dtype=newtypes)
print(df.dtypes)
Output:
name object
age int32
city object
dtype: object
我们提供字典,newtypes
,它指定列所需的数据类型。
使用 Convert_dates 处理日期
The convert_dates
参数允许您将日期字符串转换为 Pandas 日期对象。
让我们考虑一个示例,其中有以下 JSON 数据:
[
{
"name": "John",
"birthdate": "1990-05-20",
"last_login": "2022-01-01 10:30:00"
},
{
"name": "Alice",
"birthdate": "1995-02-15",
"last_login": "2022-02-05 14:45:00"
}
]
要将日期和日期时间字符串转换为 pandas 的日期时间对象,我们可以使用read_json()
函数如下:
import pandas as pd
df = pd.read_json('data.json', convert_dates=['birthdate', 'last_login'])
print(df.dtypes)
Output:
name object
birthdate datetime64[ns]
last_login datetime64[ns]
dtype: object
在上面的代码中,该文件包含 Python 字典列表。
我们指定convert_dates=['birthdate', 'last_login']
指示应转换为 pandas 的日期时间对象的列。
选择正确的编码
如果您尝试读取的 JSON 文件采用 UTF-8 以外的其他编码进行编码,则应将编码参数设置为正确的编码,以便能够正确读取数据。
import pandas as pd
try:
df = pd.read_json('arabic_data.json')
print(df.head())
except Exception as e:
print(f"An error occurred: {e}")
如果上述代码出现错误,则意味着您需要为文件选择正确的编码。
您可以使用 chardet 模块来检测文件编码,如下所示:
import chardet
def detect_encoding(file_path):
with open(file_path, 'rb') as f:
result = chardet.detect(f.read())
return result['encoding']
file_path = 'arabic_data.json'
encoding = detect_encoding(file_path)
print(f'The detected encoding of the file is: {encoding}')
请注意,在某些情况下,chardet
有时可以返回None
如果无法检测到编码,则编码不正确。在这种情况下,您应该联系文件的所有者。
获取文件编码后,您可以使用正确的编码读取文件,如下所示:
import pandas as pd
df = pd.read_json('arabic_data.json', encoding='Windows-1256')
print(df.head())
读取大型 JSON 文件
处理大型 JSON 文件时,设置lines
参数为True
可能是有益的。它允许逐行读取 JSON 对象,这样可以节省内存,并有助于处理无法放入内存的大型数据集。
让我们考虑一个示例,其中我们有一个大型 JSON 文件,其中每一行代表一个单独的 JSON 对象:
{"name": "John", "age": 44, "city": "New York"}
{"name": "Jane", "age": 32, "city": "Chicago"}
{"name": "Tom", "age": 35, "city": "San Francisco"}
{"name": "Alice", "age": 25, "city": "Boston"}
{"name": "Bob", "age": 27, "city": "Los Angeles"}
{"name": "Charlie", "age": 34, "city": "Seattle"}
{"name": "Dave", "age": 31, "city": "Austin"}
{"name": "Eve", "age": 33, "city": "Denver"}
{"name": "Frank", "age": 29, "city": "Dallas"}
{"name": "Grace", "age": 28, "city": "Miami"}
...
要逐行读取这个大的 JSON 文件,我们可以使用read_json()
功能与lines=True
并设置chunksize=1
每次读取一条记录。
在实际应用中,块大小可以是 500 左右。
import pandas as pd
start = 2
end = 5
total = 0
json_reader = pd.read_json('sample.json', lines=True, chunksize=1)
result = pd.DataFrame()
for chunk in json_reader:
if total >= start and total < end:
result = pd.concat([result, chunk])
total += 1
if total == end:
break
print(result)
Output:
name age city
2 Tom 35 San Francisco
3 Alice 25 Boston
4 Bob 27 Los Angeles
在上面的代码中,我们从索引为2的记录开始读取到索引为5的记录,每次read_json
函数根据我们设置的 chunksize 读取一条记录。
然后我们将结果块连接到 DataFrame 中。
您可以根据数据大小和可用内存调整此数字。
注意:仅当 JSON 文件中的每一行都代表有效的 JSON 对象时,此方法才有效。
使用 nrows 限制行数
处理大型 JSON 文件时,您可能并不总是需要将整个数据集加载到内存中。这nrows
参数允许您指定要从 JSON 文件读取的行数。
假设我们有一个包含数千行的大型 JSON 文件,但我们只想读取前 3 行。我们可以通过设置来实现这一点nrows=3
:
import pandas as pd
df = pd.read_json('data.json', lines=True, nrows=3)
print(df)
Output:
name age city
0 John 44 New York
1 Jane 32 Chicago
2 Tom 35 San Francisco
在上面的代码片段中,我们读取 JSON 文件“data.json”并指定nrows=3
只读取前 3 行。生成的数据框,df
,包含 JSON 文件中指定的行数。
注意:要使用nrows
参数,需要设置lines
参数为 true。
以光速
我受雇于一家大型金融服务公司,该公司一直面临与数据处理应用程序相关的低效率问题。
该应用程序旨在分析来自多个不同银行合作伙伴的持续涌入的交易数据,这些数据以大型 JSON 文件的形式出现。
这些文件包含交易时间、金额、类别和商家详细信息等数据。这些数据对于公司的风险分析和欺诈检测模块至关重要。
问题在于,该应用程序使用旧版本的 Pandas,难以处理庞大的数据量,尤其是在高峰时段。
它正在使用read_json
函数将整个数据一次性加载到 DataFrame 中。
在高峰时段,数据大小可达 10 GB。这导致了严重的延误,导致风险评估速度变慢,从而导致潜在的收入损失。
分析情况后,我意识到该应用程序在 Pandas 版本 0.20.3 上运行,这对于他们的用例来说并不是最有效的。
我采取的第一步是将 Pandas 升级到当时可用的最新版本,即 1.3.0。但是,当我开始使用以下命令实现分块时,性能显着提升read_json
。真正的痛苦是升级其他模块以使一切与新版本的 Pandas 兼容时。
通过修改代码以分块加载数据,我们能够大大减少加载时间。
这一变化导致时间急剧减少,加载时间减少了 83%!