其實前面學的根本不記得了,小丑.jpg,如果真的面試問到了估計也是一臉懵
今日任務:
JSON
先認識一下JSON和JSONL文件
記得之前在面試KIMI的時候,面試官就給我出了JSONL和EXCEL轉換的手撕代碼題,而那個時候,我連什么是JSONL都不知道,然后毫無疑問的掛了。
JSON文件
使用大括號 {} 表示對象,使用方括號 [] 表示數組,用來將所有的對象包裝在一起。
整個文件是一個有效的 JSON 對象或數組。
適合存儲結構化的數據,如配置文件、API 響應等。
一次性讀取整個文件,解析成一個 JSON 對象,可以隨機訪問其中的數據。
{
"class": "Year 1",
"student" :[
{"name": "John", "age": 30},
{"name": "Jane", "age": 25},
{"name": "Bob", "age": 40}
]}
JSONL文件
每行是一個獨立的有效 JSON 對象。
每行之間沒有逗號或其他分隔符。
適合存儲每行為獨立記錄的數據,如日志、傳感器數據、日志行等。
逐行讀取文件,逐行解析 JSON 對象,一次處理一行的數據。
{"name": "John", "age": 30}
{"name": "Jane", "age": 25}
{"name": "Bob", "age": 40}
從JSON文件加載數據
read_json() 用于從 JSON 格式的數據中讀取并加載為一個 DataFrame。它支持從 JSON 文件、JSON 字符串或 JSON 網址中加載數據。
import pandas as pddf = pd.read_json(path_or_buffer, # JSON 文件路徑、JSON 字符串或 URLorient=None, # JSON 數據的結構方式,默認是 'columns',會根據文件自動判斷dtype=None, # 強制指定列的數據類型convert_axes=True, # 是否轉換行列索引convert_dates=True, # 是否將日期解析為日期類型keep_default_na=True # 是否保留默認的缺失值標記
)
常見的 orient 參數選項:
orient 值 | JSON 格式示例 | 描述 |
---|---|---|
split | {"index":["a","b"],"columns":["A","B"],"data":[[1,2],[3,4]]} | 使用鍵?index 、columns ?和?data ?結構 |
records | [{"A":1,"B":2},{"A":3,"B":4}] | 每個記錄是一個字典,表示一行數據 |
index | {"a":{"A":1,"B":2},"b":{"A":3,"B":4}} | 使用索引為鍵,值為字典的方式 |
columns | {"A":{"a":1,"b":3},"B":{"a":2,"b":4}} | 使用列名為鍵,值為字典的方式 |
values | [[1,2],[3,4]] | 只返回數據,不包括索引和列名 |
從URL中讀取JSON數據
import pandas as pdURL = 'https://static.jyshare.com/download/sites.json'
df = pd.read_json(URL)
print(df)
JSON字符串
import pandas as pd# JSON 字符串
json_data = '''
[{"Name": "Alice", "Age": 25, "City": "New York"},{"Name": "Bob", "Age": 30, "City": "Los Angeles"},{"Name": "Charlie", "Age": 35, "City": "Chicago"}
]
'''# 從 JSON 字符串讀取數據
df = pd.read_json(json_data)print(df)#如果是下面這樣
json_data = [{"Name": "Alice", "Age": 25, "City": "New York"},{"Name": "Bob", "Age": 30, "City": "Los Angeles"},{"Name": "Charlie", "Age": 35, "City": "Chicago"}
]#用df = pd.read_json(json_data)就會報錯
df = pd.DataFrame(json_data)
如果JSON內容很多,直接print(df)可能會打印不全,用print(df.to_srting())會打印完整數據
JSON數據內嵌
假設JSON數據中包含列表
# nested_list.json
{"school_name": "ABC primary school","class": "Year 1","students": [{"id": "A001","name": "Tom","math": 60,"physics": 66,"chemistry": 61},{"id": "A002","name": "James","math": 89,"physics": 76,"chemistry": 51},{"id": "A003","name": "Jenny","math": 79,"physics": 90,"chemistry": 78}]
}
如果直接read_json
import pandas as pddf = pd.read_json('nested_list.json')print(df)
結果是
school_name class students
0 ABC primary school Year 1 {'id': 'A001', 'name': 'Tom', 'math': 60, 'phy...
1 ABC primary school Year 1 {'id': 'A002', 'name': 'James', 'math': 89, 'p...
2 ABC primary school Year 1 {'id': 'A003', 'name': 'Jenny', 'math': 79, 'p...
如果我們想把students的數據轉換成DataFrame,可以使用json_normalize()將折疊的JSON數據展平。record_path用于提取深層嵌套的列表,如果students列表嵌套在info這個字典中,則record_path可以寫成,下文的meta參數同理。
record_path=['info', 'students'] # 多層路徑用列表表示:先找 info,再找 students
import pandas as pd
import json# 使用 Python JSON 模塊載入數據
with open('nested_list.json','r') as f:data = json.loads(f.read())# 展平數據
df_nested_list = pd.json_normalize(data, record_path =['students'])
print(df_nested_list)
結果就是:
id name math physics chemistry
0 A001 Tom 60 66 61
1 A002 James 89 76 51
2 A003 Jenny 79 90 78
如果要將school_name 和 class 也作為列,則使用'meta'參數
import pandas as pd
import json# 使用 Python JSON 模塊載入數據
with open('nested_list.json','r') as f:data = json.loads(f.read())# 展平數據
df_nested_list = pd.json_normalize(data, record_path =['students'], meta=['school_name', 'class']
)
print(df_nested_list)
可以看到school_name 和 class添加到了最后兩列,且三行數據是一樣的
id name math physics chemistry school_name class
0 A001 Tom 60 66 61 ABC primary school Year 1
1 A002 James 89 76 51 ABC primary school Year 1
2 A003 Jenny 79 90 78 ABC primary school Year 1
如果JSON文件中既包含列表,又包含字典,如
{"school_name": "local primary school","class": "Year 1","info": {"president": "John Kasich","address": "ABC road, London, UK","contacts": {"email": "admin@e.com","tel": "123456789"}},"students": [{"id": "A001","name": "Tom","math": 60,"physics": 66,"chemistry": 61},{"id": "A002","name": "James","math": 89,"physics": 76,"chemistry": 51},{"id": "A003","name": "Jenny","math": 79,"physics": 90,"chemistry": 78}]
}
現在將students和info.president和info.contats.tel構成dataframe
import pandas as pd
import json# 使用 Python JSON 模塊載入數據
with open('nested_mix.json','r') as f:data = json.loads(f.read())df = pd.json_normalize(data, record_path =['students'], meta=['class',['info', 'president'], #表示先找info,再找president['info', 'contacts', 'tel']#表示先找info,再找contacts,再找tel]
)print(df)
輸出就是
id name math physics chemistry class info.president info.contacts.tel
0 A001 Tom 60 66 61 Year 1 John Kasich 123456789
1 A002 James 89 76 51 Year 1 John Kasich 123456789
2 A003 Jenny 79 90 78 Year 1 John Kasich 123456789
其他更復雜嵌套,用到glom模塊,建議直接問AI吧
不用?record_path的一個小實驗
nested_list.json
{"class": "一班","students": [{"name": "張三", "age": 18},{"name": "李四", "age": 19}]
}test.py
import pandas as pd
import json# 先使用json模塊讀取文件
with open('nested_list.json', 'r') as f:data = json.load(f)
df = pd.json_normalize(data)
print(df['students'])
會輸出
0 [{'name': '張三', 'age': 18}, {'name': '李四', 'age': 19}]
Name: students, dtype: object
因為JSON結構是頂層字典包含students鍵,所以會直接將頂層鍵students解析為一列,而students鍵是一個列表,所以students對應的值就是整個列表
df['class']
?對應的值是字符串?"一班"
df['students']
?對應的值是整個學生列表(未被進一步展開,因為它本身就是頂層鍵)
如果不用json.load,直接pd.read_json('nested_list.json'),則會報錯,因為'nested_list.json'里含有復雜嵌套,無法解析為dataframe
輸出為JSON文件
DataFrame.to_json() - 將 DataFrame 轉換為 JSON 數據,并指定JSON的結構化方式
df.to_json(path_or_buffer=None, # 輸出的文件路徑或文件對象,如果是 None 則返回 JSON 字符串orient=None, # JSON 格式方式,支持 'split', 'records', 'index', 'columns', 'values'date_format=None, # 日期格式,支持 'epoch', 'iso'default_handler=None, # 自定義非標準類型的處理函數lines=False, # 是否將每行數據作為一行(適用于 'records' 或 'split')encoding='utf-8' # 編碼格式
)
默認用columns格式轉換JSON
import pandas as pd# 創建 DataFrame
df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie'],'Age': [25, 30, 35],'City': ['New York', 'Los Angeles', 'Chicago']
})#路徑為空,則不會生成JSON文件,返回 JSON 字符串
json_str = df.to_json()print(json_str)'''
{"Name":{"0":"Alice","1":"Bob","2":"Charlie"},"Age":{"0":25,"1":30,"2":35},"City":{"0":"New York","1":"Los Angeles","2":"Chicago"}}
'''
用records模式審
import pandas as pd# 創建 DataFrame
df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie'],'Age': [25, 30, 35],'City': ['New York', 'Los Angeles', 'Chicago']
})# 將 DataFrame 轉換為 JSON 文件,指定 orient='records'
#路徑不為空
df.to_json('data.json', orient='records', lines=True)'''
{"Name":"Alice","Age":25,"City":"New York"},
{"Name":"Bob","Age":30,"City":"Los Angeles"},
{"Name":"Charlie","Age":35,"City":"Chicago"}
'''
JSON稍微有點復雜,主要是嵌套