JSON 是一種廣泛采用的基于文本的信息格式,可在系統(tǒng)之間互操作,最常見于 web 應用程序。雖然 JSON 格式是人類可讀的,但使用數(shù)據(jù)科學和數(shù)據(jù)工程工具處理它很復雜。
為了彌補這一差距, RAPIDS cuDF 提供了一個 GPU 加速的 JSON 讀取器( cudf.read_json ),該讀取器對于許多 JSON 數(shù)據(jù)結構都是高效和健壯的。 JSON format 指定了一種通用的樹狀數(shù)據(jù)結構, cuDF 實現(xiàn)了算法,可以輕松地將 JSON 樹轉換為柱狀數(shù)據(jù)。
cuDF 是一個 GPU DataFrame 庫,用于在 Python 中加載、連接、聚合、過濾和以其他方式操作數(shù)據(jù)。當 JSON 數(shù)據(jù)被構造為柱狀數(shù)據(jù)時,它可以訪問強大的 cuDF DataFrame API 。我們很高興能夠通過本讀者打開 GPU 加速到更多數(shù)據(jù)格式、項目和建模工作流的可能性。
本文重點介紹了支持的 JSON 數(shù)據(jù)選項:面向記錄的 JSON 和 JSON 行。以下是幾個 cuDF 讀取器選項的示例,用于處理具有字節(jié)范圍或多個源的 JSON 行文件。最后,您將學習如何使用 cuDF 中的工具來展平 cuDF 中的列表和結構類型,以及如何應用這些工具從常見的 JSON 模式組裝 DataFrame 。
在 cuDF 中讀取 JSON 數(shù)據(jù)
默認情況下, cuDF JSON 讀取器需要使用 records 方向的輸入數(shù)據(jù)。面向記錄的 JSON 數(shù)據(jù)由根級別的對象數(shù)組組成,數(shù)組中的每個對象對應一行。對象中的字段名決定表的列名。
JSON 數(shù)據(jù)的另一個常見變體是 JSON 行,其中 JSON 對象由換行符(n)分隔,每個對象對應一行。
以下代碼示例顯示了面向記錄的 JSON 以及 JSON 行數(shù)據(jù):
>>> j = '''[
... {"a": "v1", "b": 12},
... {"a": "v2", "b": 7},
... {"a": "v3", "b": 5}
... ]'''
>>> df_records = cudf.read_json(j)
>>> j = 'n'.join([
... '{"a": "v1", "b": 12}',
... '{"a": "v2", "b": 7}',
... '{"a": "v3", "b": 5}'
... ])
>>> df_lines = cudf.read_json(j, lines=True)
>>> df_lines
a b
0 v1 12
1 v2 7
2 v3 5
>>> df_records.equals(df_lines)
True
cuDF JSON 讀取器還與嵌套的 JSON 對象和數(shù)組兼容,這些對象和數(shù)組大致映射到結構和列表 data types in cuDF 。
以下示例演示了用于生成列表和結構列以及數(shù)據(jù)類型為列表和結構的任意組合的列的輸入和輸出。
# example with columns types:
# list and struct
>>> j = '''[
... {"list": [0, 1, 2], "struct": {"k": "v1"}},
... {"list": [3, 4, 5], "struct": {"k": "v2"}}
... ]'''
>>> df = cudf.read_json(j)
>>> df
list struct
0 [0, 1, 2] {'k': 'v1'}
1 [3, 4, 5] {'k': 'v2'}
# example with columns types:
# list> and struct, m:int>
>>> j = 'n'.join([
... '{"a": [{"k": 0}], "b": {"k": [0, 1], "m": 5}}',
... '{"a": [{"k": 1}, {"k": 2}], "b": {"k": [2, 3], "m": 6}}',
... ])
>>> df = cudf.read_json(j, lines=True)
>>> df
a b
0 [{'k': 0}] {'k': [0, 1], 'm': 5}
1 [{'k': 1}, {'k': 2}] {'k': [2, 3], 'm': 6}
處理大小 JSON 行文件
對于基于 JSON Lines 數(shù)據(jù)的工作負載, cuDF 包括幫助數(shù)據(jù)處理的讀取器選項:大文件的字節(jié)范圍支持和小文件的多源支持。
字節(jié)范圍支持
一些工作流,如欺詐檢測和用戶行為建模,需要處理可能超過 GPU 內(nèi)存容量的大型 JSON Line 文件。
cuDF 中的 JSON 讀取器支持字節(jié)范圍參數(shù),該參數(shù)指定起始字節(jié)偏移量和字節(jié)大小。讀取器解析在字節(jié)范圍內(nèi)開始的每個記錄,因此,字節(jié)范圍不必與記錄邊界對齊。
在分布式工作流中,字節(jié)范圍使每個工作人員能夠處理數(shù)據(jù)的子集。在過濾和聚合中,字節(jié)范圍允許單個工作人員以塊的形式處理數(shù)據(jù)。
為了避免跳過行或讀取重復的行,字節(jié)范圍應該相鄰,如下例所示。
>>> num_rows = 10
>>> j = 'n'.join([
... '{"id":%s, "distance": %s, "unit": "m/s"}' % x
... for x in zip(range(num_rows), cupy.random.rand(num_rows))
... ])
>>> chunk_count = 4
>>> chunk_size = len(j) // chunk_count + 1
>>> data = []
>>> for x in range(chunk_count):
... d = cudf.read_json(
... j,
... lines=True,
... byte_range=(chunk_size * x, chunk_size)
... )
... data.append(d)
>>> df = cudf.concat(data)
多源支持
相比之下,一些工作流需要處理許多小的 JSON 行文件。
cuDF 中的 JSON 讀取器接受數(shù)據(jù)源列表,而不是循環(huán)通過源并連接生成的 DataFrame 。然后將原始輸入作為單個源進行有效處理。
cuDF 中的 JSON 讀取器接受源作為文件路徑、原始字符串或類似文件的對象,以及這些源的列表。
>>> j1 = '{"id":0}n{"id":1}n'
>>> j2 = '{"id":2}n{"id":3}n'
>>> df = cudf.read_json([j1, j2], lines=True)
解包列表和結構數(shù)據(jù)
將 JSON 數(shù)據(jù)讀入帶有列表和結構列類型的 cuDF DataFrame 后,許多工作流的下一步是將數(shù)據(jù)提取或展平為簡單類型。
對于結構列,一種解決方案是使用struct.explode訪問器提取數(shù)據(jù),并將結果連接到父 DataFrame 。
下面的代碼示例演示如何從結構列中提取數(shù)據(jù)。
>>> j = 'n'.join([
... '{"x": "Tokyo", "y": {"country": "Japan", "iso2": "JP"}}',
... '{"x": "Jakarta", "y": {"country": "Indonesia", "iso2": "ID"}}',
... '{"x": "Shanghai", "y": {"country": "China", "iso2": "CN"}}'
... ])
>>> df = cudf.read_json(j, lines=True)
>>> df = df.drop(columns='y').join(df['y'].struct.explode())
>>> df
x country iso2
0 Tokyo Japan JP
1 Jakarta Indonesia ID
2 Shanghai China CN
對于元素順序有意義的列表列,list.get訪問器從特定位置提取元素。然后,可以將生成的cudf.Series對象分配給 DataFrame 中的新列。
下面的代碼示例演示如何從列表列中提取第一個和第二個元素。
>>> j = 'n'.join([
... '{"name": "Peabody, MA", "coord": [42.53, -70.98]}',
... '{"name": "Northampton, MA", "coord": [42.32, -72.66]}',
... '{"name": "New Bedford, MA", "coord": [41.63, -70.93]}'
... ])
>>> df = cudf.read_json(j, lines=True)
>>> df['latitude'] = df['coord'].list.get(0)
>>> df['longitude'] = df['coord'].list.get(1)
>>> df = df.drop(columns='coord')
>>> df
name latitude longitude
0 Peabody, MA 42.53 -70.98
1 Northampton, MA 42.32 -72.66
2 New Bedford, MA 41.63 -70.93
最后,對于長度可變的列表列,explode方法將創(chuàng)建一個新的 DataFrame ,每個列表元素作為一行。將分解的 DataFrame 連接到父 DataFrame 上會產(chǎn)生一個具有所有簡單類型的輸出。
以下示例展平列表列,并將其連接到父 DataFrame 中的索引和其他數(shù)據(jù)。
>>> j = 'n'.join([
... '{"product": "socks", "ratings": [2, 3, 4]}',
... '{"product": "shoes", "ratings": [5, 4, 5, 3]}',
... '{"product": "shirts", "ratings": [3, 4]}'
... ])
>>> df = cudf.read_json(j, lines=True)
>>> df = df.drop(columns='ratings').join(df['ratings'].explode())
>>> df
product ratings
0 socks 2
0 socks 4
0 socks 3
1 shoes 5
1 shoes 5
1 shoes 4
1 shoes 3
2 shirts 3
2 shirts 4
使用 cuDF 構建 JSON 數(shù)據(jù)解決方案
有時,工作流必須使用對象根處理 JSON 數(shù)據(jù)。 cuDF 提供了為此類數(shù)據(jù)構建解決方案的工具。要使用對象根處理 JSON 數(shù)據(jù),我們建議將數(shù)據(jù)作為單個 JSON 行讀取,然后拆包生成的 DataFrame 。
以下示例將 JSON 對象作為單行讀取,然后將“ results ”字段提取到新的 DataFrame 中。
>>> j = '''{
... "metadata" : {"vehicle":"car"},
... "results": [
... {"id": 0, "distance": 1.2},
... {"id": 1, "distance": 2.4},
... {"id": 2, "distance": 1.7}
... ]
... }'''
# first read the JSON object with lines=True
>>> df = cudf.read_json(j, lines=True)
>>> df
metadata records
0 {'vehicle': 'car'} [{'id': 0, 'distance': 1.2}, {'id': 1, 'distan...
# then explode the 'records' column
>>> df = df['records'].explode().struct.explode()
>>> df
id distance
0 0 1.2
1 1 2.4
2 2 1.7
關鍵要點
cuDF JSON 讀取器旨在加速廣泛的 JSON 數(shù)據(jù)工作負載,包括跨大文件和小文件的簡單和復雜類型。
這篇文章演示了 cuDF JSON 讀取器與面向記錄和 JSON 行數(shù)據(jù)的常見用法,以及展示字節(jié)范圍和多源支持。現(xiàn)在,您可以加快處理 JSON 數(shù)據(jù)的方式,并將 JSON 數(shù)據(jù)有效地結合到工作流中。
-
NVIDIA
+關注
關注
14文章
5570瀏覽量
109383 -
gpu
+關注
關注
28文章
5150瀏覽量
134748 -
AI
+關注
關注
91文章
39083瀏覽量
299643
發(fā)布評論請先 登錄
JSON 數(shù)據(jù)格式
怎么支持PIC32中的JSON解析和序列化
json數(shù)據(jù)解析
android使用JSON進行網(wǎng)絡數(shù)據(jù)交換
java生成json格式數(shù)據(jù) 和 java遍歷json格式數(shù)據(jù)
PHP如何返回json格式的數(shù)據(jù)給jquery的詳細資料說明
什么是JSON劫持 JSON和XML的區(qū)別
什么是JSON JSON的語法規(guī)則
645儀表以JSON格式上發(fā)方法
怎么用C+JS結構來處理JSON數(shù)據(jù)?
Spring Boot時配置JSON序列化選項的幾種方法
如何利用Python和pandas來處理json數(shù)據(jù)
支持的JSON數(shù)據(jù)選項介紹
評論