基于polars的檔案,可以使用json_path_match將JSON欄位提取成字串系列。
但是我們可以做一些事情,比如pandas.Series.map(json.loads)一次轉換整個 JSON 字串嗎?然后可以進一步將加載的 JSON 系列轉換為具有健全 dtypes 的另一個資料幀。
我知道我可以先進入pandas,但我正在尋找進入的方法polars。
uj5u.com熱心網友回復:
我應該首先指出,有一種polars.read_json方法。例如:
import polars as pl
import io
json_file = """[{"a":"1", "b":10, "c":[1,2,3]},
{"a":"2", "b":20, "c":[3,4,5]},
{"a":"3.1", "b":30.2, "c":[8,8,8]},
{"a":"4", "b":40.0, "c":[9,9,90]}]
"""
pl.read_json(io.StringIO(json_file))
shape: (4, 3)
┌─────┬──────┬────────────┐
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ str ┆ f64 ┆ list [i64] │
╞═════╪══════╪════════════╡
│ 1 ┆ 10.0 ┆ [1, 2, 3] │
├?????┼??????┼????????????┤
│ 2 ┆ 20.0 ┆ [3, 4, 5] │
├?????┼??????┼????????????┤
│ 3.1 ┆ 30.2 ┆ [8, 8, 8] │
├?????┼??????┼????????????┤
│ 4 ┆ 40.0 ┆ [9, 9, 90] │
└─────┴──────┴────────────┘
但是要回答您關于已加載到系列中的 JSON 資料的具體問題,我認為您正在尋找的是polars.Series.apply方法,它將對 Polars 系列的每個單元格應用一個可呼叫函式。
例如,假設我們已經將以下 JSON 欄位加載到 Polars DataFrame 的系列中:
import json
import polars as pl
df = pl.DataFrame(
{
"json_val": [
'{"a":"1", "b":10, "c":[1,2,3]}',
'{"a":"2", "b":20, "c":[3,4,5]}',
'{"a":"3.1", "b":30.2, "c":[8,8,8]}',
'{"a":"4", "b":40.0, "c":[9,9,90]}',
]
}
)
print(df)
shape: (4, 1)
┌─────────────────────────────────────┐
│ json_val │
│ --- │
│ str │
╞═════════════════════════════════════╡
│ {"a":"1", "b":10, "c":[1,2,3]} │
├?????????????????????????????????????┤
│ {"a":"2", "b":20, "c":[3,4,5]} │
├?????????????????????????????????????┤
│ {"a":"3.1", "b":30.2, "c":[8,8,8... │
├?????????????????????????????????????┤
│ {"a":"4", "b":40.0, "c":[9,9,90]... │
└─────────────────────────────────────┘
我們可以使用apply和json.loads功能。在這個例子中,這將產生一個 Series 型別struct:
df.select(pl.col("json_val").apply(json.loads))
shape: (4, 1)
┌──────────────────────────┐
│ json_val │
│ --- │
│ struct[3]{'a', 'b', 'c'} │
╞══════════════════════════╡
│ {"1",10,[1, 2, 3]} │
├??????????????????????????┤
│ {"2",20,[3, 4, 5]} │
├??????????????????????????┤
│ {"3.1",30,[8, 8, 8]} │
├??????????????????????????┤
│ {"4",40,[9, 9, 90]} │
└──────────────────────────┘
(注意一點,注意列是如何b被截斷為整數的。)
根據 JSON 的結構,您還可以使用該polars.DataFrame.unnest函式將json_valstruct 列拆分為單獨的列。
df.select(pl.col("json_val").apply(json.loads)).unnest("json_val")
shape: (4, 3)
┌─────┬─────┬────────────┐
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ list [i64] │
╞═════╪═════╪════════════╡
│ 1 ┆ 10 ┆ [1, 2, 3] │
├?????┼?????┼????????????┤
│ 2 ┆ 20 ┆ [3, 4, 5] │
├?????┼?????┼????????????┤
│ 3.1 ┆ 30 ┆ [8, 8, 8] │
├?????┼?????┼????????????┤
│ 4 ┆ 40 ┆ [9, 9, 90] │
└─────┴─────┴────────────┘
這有助于您入門嗎?
編輯:處理型別轉換問題
我對任何無型別輸入檔案(尤其是 csv 檔案)使用的一種通用策略是將所有值作為字串/polars.Utf8型別回傳。這樣,在我有機會直觀地檢查結果之后,我可以顯式地轉換型別。(我經常被“自動”型別轉換所困擾。)
該json.loads方法有兩個有用的關鍵字選項parse_float,parse_int在這種情況下會有所幫助。我們可以使用一個簡單的 lambda 函式來告訴 json 決議器將整數和浮點列保留為字串。
# define our own translate function to keep floats/ints as strings
def json_translate(json_str: str):
return json.loads(json_str, parse_float=lambda x: x, parse_int=lambda x: x)
df.select(pl.col("json_val").apply(f=json_translate))
shape: (4, 1)
┌────────────────────────────────┐
│ json_val │
│ --- │
│ struct[3]{'a', 'b', 'c'} │
╞════════════════════════════════╡
│ {"1","10",["1", "2", "3"]} │
├????????????????????????????????┤
│ {"2","20",["3", "4", "5"]} │
├????????????????????????????????┤
│ {"3.1","30.2",["8", "8", "8"]} │
├????????????????????????????????┤
│ {"4","40.0",["9", "9", "90"]} │
└────────────────────────────────┘
請注意,所有整數和浮點值都保留為字串,并且在我們使用unnest函式時保持不變(下面的列標題顯示“str”)。
df.select(pl.col("json_val").apply(f=json_translate)).unnest('json_val')
shape: (4, 3)
┌─────┬──────┬──────────────────┐
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ str ┆ str ┆ list [str] │
╞═════╪══════╪══════════════════╡
│ 1 ┆ 10 ┆ ["1", "2", "3"] │
├?????┼??????┼??????????????????┤
│ 2 ┆ 20 ┆ ["3", "4", "5"] │
├?????┼??????┼??????????????????┤
│ 3.1 ┆ 30.2 ┆ ["8", "8", "8"] │
├?????┼??????┼??????????????????┤
│ 4 ┆ 40.0 ┆ ["9", "9", "90"] │
└─────┴──────┴──────────────────┘
從這一點開始,您可以使用 Polars 的cast運算式將字串轉換為您想要的特定數字型別。這是一個堆疊溢位問題,可以幫助解決cast.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/467795.html
