在 pandas 中使用 read_json 导入单个记录
Posted
技术标签:
【中文标题】在 pandas 中使用 read_json 导入单个记录【英文标题】:Importing single record using read_json in pandas 【发布时间】:2015-10-17 19:30:12 【问题描述】:我正在尝试使用函数导入 json 文件:
sku = pandas.read_json('https://cws01.worldstores.co.uk/api/product.php?product_sku=125T:FT0111')
但是,我不断收到以下错误
ValueError: 数组的长度必须相同
我应该怎么做才能将其正确导入数据框?
这是json的结构:
"id": "5",
"sku": "JOSH:BECO-BRN",
"last_updated": "2013-06-10 15:46:22",
...
"propertyType1": [
"manufacturer_colour"
],
"category": [
"category_id": "10",
"category_name": "All Products"
,
...
"category_id": "238",
"category_name": "All Sofas"
],
"root_categories": [
"516"
],
"url": "/p/Beco Suede Sofa Bed?product_id=5",
"item": [
"2"
],
"image_names": "[\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/L\\/19\\/Beco_Suede_Sofa_Bed-1.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/P\\/19\\/Beco_Suede_Sofa_Bed-1.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/SP\\/19\\/Beco_Suede_Sofa_Bed-1.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/SS\\/19\\/Beco_Suede_Sofa_Bed-1.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/ST\\/19\\/Beco_Suede_Sofa_Bed-1.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/WP\\/19\\/Beco_Suede_Sofa_Bed-1.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/L\\/19\\/Beco_Suede_Sofa_Bed-2.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/P\\/19\\/Beco_Suede_Sofa_Bed-2.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/SP\\/19\\/Beco_Suede_Sofa_Bed-2.jpg\",\"https:\\/\\/cdn.worldstores.co.uk \\/images\\/products\\/SS\\/19\\/Beco_Suede_Sofa_Bed-2.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/ST\\/19\\/Beco_Suede_Sofa_Bed-2.jpg\",\"https:\\/\\/cdn.worldstores.co.uk\\/images\\/products\\/WP\\/19\\/Beco_Suede_Sofa_Bed-2.jpg\"]"
【问题讨论】:
我需要创建一个自包含的python脚本来处理几个json文件 您能描述一下您设想的结构将如何转换为数据框吗?您想展平嵌套结构吗? 我已经添加了json结构 我遇到了同样的问题。我通过将 '[' ']' 附加到 JSON 的开头和结尾并设置 orient="records" 来解决它。 【参考方案1】:The pandas.read_json
function 采用多种格式。
由于您没有指定 json 文件的格式(orient=
属性),pandas 将默认相信您的数据是列式的。下面讨论了 pandas 期望的不同格式。
你试图从https://cws01.worldstores.co.uk/api/product.php?product_sku=125T:FT0111解析的数据 似乎不符合任何受支持的格式,因为它似乎只是一个“记录”。 Pandas 期待某种收藏。
您可能应该尝试将多个条目收集到一个文件中,然后使用read_json
函数对其进行解析。
编辑:
获取多行并使用pandas.read_json
函数解析它的简单方法:
import urllib2
import pandas as pd
url_base = "https://cws01.worldstores.co.uk/api/product.php?product_sku="
products = ["125T:FT0111", "125T:FT0111", "125T:FT0111"]
raw_data_list = []
for sku in products:
url = url_base.format(sku)
raw_data_list.append(urllib2.urlopen(url).read())
data = "[" + (",".join(raw_data_list)) + "]"
data = pd.read_json(data, orient='records')
data
/编辑
我对 pandas.read_json 函数格式的看法。
The pandas.read_json
function 是 pandas 试图将尽可能多的功能集成到单个函数中的又一个光辉例子。这当然会导致一个非常复杂的函数。
系列
如果您的数据是Series
,则pandas.read_json(orient=)
默认为'index'
在解析 Series
时允许的 orient 值是:'split','records','index'
请注意,orient='index'
的系列索引必须是唯一的。
数据帧
如果您的数据是DataFrame
,则pandas.read_json(orient=)
默认为'columns'
在解析 DataFrame
时允许的 orient 值是:
'split','records','index','columns','values'
请注意,orient='index'
和 orient='columns'
的 Series 索引必须唯一,orient='index'
、orient='columns'
和 orient='records'
的 DataFrame 列必须唯一。
格式
无论您的数据是DataFrame
还是Series
,orient=
都会期望数据格式相同:
拆分
期望像 DataFrame
构造函数所采用的 dict 的字符串表示形式:
"index":[1,2,3,4], "columns":["col1","col2"], "data":[[8,7,6,5], [5,6,7,8]]
记录
期望字典列表的字符串表示,例如:
["col1":8,"col2":5,"col1":7,"col2":6,"col1":6,"col2":7,"col1":5,"col2":8]
注意这里没有设置索引。
索引
期望嵌套 dict dict 的字符串表示形式,例如:
"1":"col1":8,"col2":5,"2":"col1":7,"col2":6,"3":"col1":6,"col2":7,"4":"col1":5,"col2":8
值得注意的是,它不接受字符串以外的其他类型的索引。可能会在以后的版本中修复。
列
期望嵌套字典的字符串表示,例如:
"col1":"1":8,"2":7,"3":6,"4":5,"col2":"1":5,"2":6,"3":7,"4":8
价值观
期望列表的字符串表示形式,如:
[[8, 5],[7, 6],[6, 7],[5, 8]]
结果数据帧
在大多数情况下,你得到的数据框会是这样的,上面有 json 字符串:
col1 col2
1 8 5
2 7 6
3 6 7
4 5 8
【讨论】:
【参考方案2】:也许这不是最优雅的解决方案,但给了我我想要的东西,或者至少我相信如此,如果有问题,请随时警告
url = "https://cws01.worldstores.co.uk/api/product.php?product_sku=125T:FT0111"
data = urllib2.urlopen(url).read()
data = json.loads(data)
data = pd.DataFrame(data.items())
data = data.transpose()
【讨论】:
我在回答中改进了这个版本,仍然使用 pd.read_json。【参考方案3】:另一种解决方案是使用 try except。
json_path='https://cws01.worldstores.co.uk/api/product.php?product_sku=125T:FT0111'
try: a=pd.read_json(json_path)
except ValueError: a=pd.read_json("["+json_path+"]")
【讨论】:
【参考方案4】:迭代@firelynx 的答案:
#! /usr/bin/env python3
from urllib.request import urlopen
import pandas as pd
products = ["125T:FT0111", "125T:FT0111", "125T:FT0111"]
raw_lines = ""
for sku in products:
url = f"https://cws01.worldstores.co.uk/api/product.php?product_sku=sku"
raw_lines += urlopen(url).read() + "\n"
data = pd.read_json(raw_lines, lines=True)
这将支持返回单个 JSON 对象或一堆换行符 ('\n') 分隔的任何源。
或者这个单线(ish)应该是一样的:
#! /usr/bin/env python3
import pandas as pd
products = ["125T:FT0111", "125T:FT0111", "125T:FT0111"]
data = pd.concat(
pd.read_json(
f"https://cws01.worldstores.co.uk/api/product.php?product_sku=sku",
lines=True
) for sku in products
)
PS:这里python3只支持fstring,所以你应该使用str.format来兼容python2。
【讨论】:
以上是关于在 pandas 中使用 read_json 导入单个记录的主要内容,如果未能解决你的问题,请参考以下文章
在 Pandas UnicodeDecodeError 中无法使用 pandas.read_json() 解码 JSON 文件中的 Unicode Ascii
使用 pandas.read_json 时出现 ValueError
如何让 pandas.read_json 将此 API 返回识别为有效的 .json?
如何在 ```pandas.read_json(...)` 期间修复 ```ValueError: Trailing data```?