[英]Read large .json file with index format into Pandas dataframe
我一直在關注這個答案,但在與它的作者討論之后,它似乎只為orient='records'
數據格式提供了一個解決方案。
這是區別:
# orient='records'
[
{"Product":"Desktop Computer","Price":700},
{"Product":"Tablet","Price":250},
{"Product":"iPhone","Price":800},
{"Product":"Laptop","Price":1200}
]
# orient='index'
{
"0":{"Product":"Desktop Computer","Price":700},
"1":{"Product":"Tablet","Price":250},
"2":{"Product":"iPhone","Price":800},
"3":{"Product":"Laptop","Price":1200}
}
我有索引格式,因為我的數據來自 SQL 數據庫讀入 dataframe 並且需要索引字段來指定每條記錄。
我的 json 文件為 2.5 GB ,已從 dataframe 以orient='index'
格式導出。
df.to_json('test.json', orient='index')
這意味着整個文件實際上是一個巨大的字符串,而不是像記錄集合這樣的列表:
{"0":{"Product":"Desktop Computer","Price":700},"1":{"Product":"Tablet","Price":250},"2":{"Product":"iPhone","Price":800},"3":{"Product":"Laptop","Price":1200}}
這意味着我不能像這樣使用任何基於行或塊的迭代解決方案:
df = pd.read_json('test.json', orient='index', lines=True, chunksize=5)
根據文檔, lines=True
只能在記錄采用類似列表的格式時使用,這就是為什么pandas.DataFrame.to_json
甚至不接受這個參數,除非 orient 不是orient='records'
。 chunksize=
的限制也來自於此,它說:
"This can only be passed if lines=True. If this is None, the file will be read into memory all at once."
這正是問題的原因,試圖讀取如此巨大的.json 文件返回:
df = pd.read_json('test.json', orient='index')
File "C:\Users\Username\AppData\Local\Programs\Python\Python37\lib\site-
packages\pandas\io\json\_json.py", line 1100,
in _parse_no_numpy
loads(json, precise_float=self.precise_float),
MemoryError
我也在考慮將索引值添加為第一列,在這種情況下,它不會因記錄格式而丟失; 或者甚至可以單獨存儲一個索引列表。 只是我擔心它會在以后降低搜索性能。
是否有任何解決方案來嚴格使用.json文件而不使用其他數據庫或基於大數據的技術來處理這種情況?
更新#1
這里的請求是我的數據的實際結構。 SQL 表:
Serial Date PatientID Type Gender YearWeek
0 425571118001461E 2011-06-30 20:59:30 186092 3 1.0 2011-w26
1 425571118001461E 2011-06-30 20:55:30 186092 3 1.0 2011-w26
2 425571118001461E 2013-08-28 09:29:30 186092 3 1.0 2013-w35
3 425571118001461E 2013-08-28 07:44:30 186092 3 1.0 2013-w35
4 425571118001461E 2013-08-27 20:44:30 186092 3 1.0 2013-w35
... ... ... ... ... ... ...
32290281 4183116300254921 2020-04-09 08:07:50 217553 8 2.0 2020-w15
32290282 4183116300254921 2020-04-08 10:29:50 217553 8 2.0 2020-w15
32290283 4141119420031548 2020-04-20 10:18:02 217555 12 2.0 2020-w17
32290284 4141119420043226 2020-04-20 12:33:11 217560 12 NaN 2020-w17
32290285 4141119420000825 2020-04-20 17:31:44 217568 12 1.0 2020-w17
pandas pivot 表與示例中的表幾乎相同,但有 50,000 行和 4,000 列:
df = df.pivot_table(index='PatientID', values='Serial', columns='YearWeek', aggfunc=len, fill_value=0)
YearWeek 1969-w01 1969-w02 1969-w03 1969-w04 1969-w05 ... 2138-w17 2138-w18 2138-w19 2138-w20 2138-w21
PatientID
0 0 0 0 0 0 ... 0 0 0 0 0
455 1 0 3 0 0 ... 0 0 0 0 0
40036 0 0 0 0 0 ... 0 0 0 0 0
40070 0 0 0 0 0 ... 0 0 0 0 0
40082 0 0 0 0 0 ... 0 0 0 0 0
... ... ... ... ... ... ... ... ... ... ... ...
217559 0 0 0 0 0 ... 0 0 0 0 0
217560 0 0 0 0 0 ... 0 0 0 0 0
217561 0 0 0 0 0 ... 0 0 0 0 0
217563 0 0 0 0 0 ... 0 0 0 0 0
217568 0 1 0 2 0 ... 0 0 0 0 0
這就是使用格式為 json 的索引保存它的方式:
{
"0":{"1969-w01":0,"1969-w02":0,"1969-w03":0,"1969-w04":0, ...},
"455":{"1969-w01":1,"1969-w02":0,"1969-w03":3,"1969-w04":0, ...},
"40036":{"1969-w01":0,"1969-w02":0,"1969-w03":0,"1969-w04":0, ...},
...
"217568":{"1969-w01":0,"1969-w02":1,"1969-w03":0,"1969-w04":2, ...}
}
只有我不能給出line=True
arg,所以它實際上被限制在一個巨大的字符串中,使它成為一個單線 json:
{"0":{"1969-w01":0,"1969-w02":0,"1969-w03":0,"1969-w04":0, ...},"455":{"1969-w01":1,"1969-w02":0,"1969-w03":3,"1969-w04":0, ...},"40036":{"1969-w01":0,"1969-w02":0,"1969-w03":0,"1969-w04":0, ...}, ... "217568":{"1969-w01":0,"1969-w02":1,"1969-w03":0,"1969-w04":2, ...}}
一些解決方案,從最簡單到涉及更多:
如果您可以在數據庫上執行查詢,也許最好的解決方案是嘗試以更好的格式寫入數據? 或者,您可以嘗試直接從數據庫中讀取 - Pandas 也可以這樣做:) 這是pd.read_sql() 的文檔。
orient=...
有必要嗎?要按照您給出的示例讀取 JSON 文件,並創建一個與您的數據透視表示例相當的形式的 DataFrame(JSON 鍵為 dataframe 索引,您可以嘗試以下簡單方法:
# read and transpose!
df = pd.read_json("test.json").T
但是,這可能無法解決 memory 問題。
也許最快的方法是簡單地將大文件切割成更小的文件,每個文件都可以讀取到 Pandas Dataframe (限制工作pd.concat
pd.merge
Linux 中有一個很好的工具,叫做split
,它可以做到。 我注意到您正在使用 windows(如果您啟用它,較新的 windows 版本會提供 Linux 終端。),否則可能有類似的工具。 但我不知道我害怕。
如果您只需要這樣做一次然后繼續您的生活,您也許可以使用 Emacs 或 VS Code 等文本編輯器打開您的文件,然后將部分復制粘貼到新文件中......蹩腳,但可能會工作¯ \_(ツ)_/¯
一個名為 ijson 的ijson
將迭代加載 JSON 文件,該文件允許您定義中斷或對每個嵌套分區進行處理 - 例如,您可以創建 Z251D2BBFE9A3B95E5691CEB3DC上的records
格式。 該解決方案還承諾低 memory 消耗,作為一個迭代器(又名生成器) - 你需要了解它是如何工作的。 看看這里有一個很好的解釋。
另一個名為json-streamer 的package 也可以讀取部分 JSON 內容,盡管它可能有點遠,因為您有一個 static 文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.