簡體   English   中英

將 pandas 類 json 字符串列轉換為 DataFrame

[英]Convert pandas column of json-like strings to DataFrame

我有以下 DataFrame,我從 API 中“按原樣”獲得:

df = pd.DataFrame({'keys': {0: "[{'contract': 'G'}, {'contract_type': 'C'}, {'strike': '560'}, {'strip': '10/1/2022'}]",
                            1: "[{'contract': 'G'}, {'contract_type': 'P'}, {'strike': '585'}, {'strip': '10/1/2022'}]",
                            2: "[{'contract': 'G'}, {'contract_type': 'C'}, {'strike': '580'}, {'strip': '10/1/2022'}]",
                            3: "[{'contract': 'G'}, {'contract_type': 'C'}, {'strike': '545'}, {'strip': '10/1/2022'}]",
                            4: "[{'contract': 'G'}, {'contract_type': 'P'}, {'strike': '555'}, {'strip': '10/1/2022'}]"},
                   'value': {0: 353.3, 1: 25.8, 2: 336.65, 3: 366.05, 4: 20.8}})

>>> df
                                                keys   value
0  [{'contract': 'G'}, {'contract_type': 'C'}, {'...  353.30
1  [{'contract': 'G'}, {'contract_type': 'P'}, {'...   25.80
2  [{'contract': 'G'}, {'contract_type': 'C'}, {'...  336.65
3  [{'contract': 'G'}, {'contract_type': 'C'}, {'...  366.05
4  [{'contract': 'G'}, {'contract_type': 'P'}, {'...   20.80

“鍵”列的每一行都是一個字符串(不是 JSON,因為值用單引號而不是雙引號括起來)。 例如:

>>> df.at[0, keys]
"[{'contract': 'G'}, {'contract_type': 'C'}, {'strike': '560'}, {'strip': '10/1/2022'}]"

我想將“鍵”列轉換為 DataFrame 和 append 作為新列轉換為df

我目前正在做:

  1. 用雙引號替換單引號並傳遞給json.loads以讀入具有以下結構的字典列表:
[{'contract': 'G'}, {'contract_type': 'C'}, {'strike': '560'}, {'strip': '10/1/2022'}]
  1. 通過字典理解將字典組合成一個字典:
{'contract': 'G', 'contract_type': 'C', 'strike': '560', 'strip': '10/1/2022'}
  1. 將此apply到每一行並在結果上調用pd.DataFrame構造函數。
  2. join原來的df

在一行中,我的代碼是:

>>> df.drop("keys", axis=1).join(pd.DataFrame(df["keys"].apply(lambda x: {k: v for d in json.loads(x.replace("'","\"")) for k, v in d.items()}).tolist()))

    value contract contract_type strike      strip
0  353.30        G             C    560  10/1/2022
1   25.80        G             P    585  10/1/2022
2  336.65        G             C    580  10/1/2022
3  366.05        G             C    545  10/1/2022
4   20.80        G             P    555  10/1/2022

我想知道是否有更好的方法來做到這一點。

您可以使用ast.literal_eval (內置)將字典字符串轉換為實際字典,然后使用pd.json_normalizerecord_path=[[]]將對象轉換為表格格式:

import ast
new_df = pd.json_normalize(df['keys'].apply(ast.literal_eval), record_path=[[]]).apply(lambda col: col.dropna().tolist())

Output:

>>> new_df
  contract contract_type strike      strip
0        G             C    560  10/1/2022
1        G             P    585  10/1/2022
2        G             C    580  10/1/2022
3        G             C    545  10/1/2022
4        G             P    555  10/1/2022

另一種解決方案是使用字符串替換將單獨的字典合並為一個:

import ast
new_df = pd.DataFrame(df['keys'].str.replace("'}, {'", "', '", regex=True).apply(ast.literal_eval).str[0].tolist())

Output:


還有另一種選擇,這個使用functools.reduce (內置):

import ast
new_df = pd.DataFrame(df['keys'].apply(ast.literal_eval).apply(lambda row: functools.reduce(lambda x, y: x | y, row)).tolist())

您可以使用ast.literal_evalChainMap集合將字典列表合並為單個字典。

from collections import ChainMap

df['keys'] = df['keys'].apply(ast.literal_eval).apply(lambda x: dict(ChainMap(*x)))

print(df)
                                               keys   value
0  {'strip': '10/1/2022', 'strike': '560', 'contr...  353.30
1  {'strip': '10/1/2022', 'strike': '585', 'contr...   25.80
2  {'strip': '10/1/2022', 'strike': '580', 'contr...  336.65
3  {'strip': '10/1/2022', 'strike': '545', 'contr...  366.05
4  {'strip': '10/1/2022', 'strike': '555', 'contr...   20.80

然后使用.apply(pd.Series)將一列字典分解為單獨的列,並使用concat將其與 dataframe 的 rest 合並

df_ = pd.concat([df['keys'].apply(pd.Series), df['value']], axis=1)

print(df_)
       strip strike contract_type contract   value
0  10/1/2022    560             C        G  353.30
1  10/1/2022    585             P        G   25.80
2  10/1/2022    580             C        G  336.65
3  10/1/2022    545             C        G  366.05
4  10/1/2022    555             P        G   20.80

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM