我正在尝试将一个321 MB
嵌套的json文件转换为熊猫Dataframe
,这使我非常非常很长时间了,我确信一种更快的方法,这是我的代码:
这是数据的样子:
js_dict["data"][0:5]
d = [{'datetime': '2013-01-01T00:00:00+02:00', 'channels': [
{'id': 1, 'name': 'Rain', 'alias': None, 'value': 0.0, 'status': 1, 'valid': True, 'description': None},
{'id': 2, 'name': 'WSmax', 'alias': None, 'value': 7.7, 'status': 1, 'valid': True, 'description': None},
{'id': 3, 'name': 'WDmax', 'alias': None, 'value': 52.0, 'status': 1, 'valid': True, 'description': None},
{'id': 4, 'name': 'WS', 'alias': None, 'value': 5.2, 'status': 1, 'valid': True, 'description': None},
{'id': 5, 'name': 'WD', 'alias': None, 'value': 56.0, 'status': 1, 'valid': True, 'description': None},
{'id': 6, 'name': 'STDwd', 'alias': None, 'value': 11.9, 'status': 1, 'valid': True, 'description': None},
{'id': 7, 'name': 'RH', 'alias': None, 'value': 55.0, 'status': 1, 'valid': True, 'description': None},
{'id': 8, 'name': 'TD', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 10, 'name': 'TDmax', 'alias': None, 'value': 13.6, 'status': 1, 'valid': True, 'description': None},
{'id': 11, 'name': 'TDmin', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 13, 'name': 'WS1mm', 'alias': None, 'value': 6.2, 'status': 1, 'valid': True, 'description': None},
{'id': 14, 'name': 'Ws10mm', 'alias': None, 'value': 5.3, 'status': 1, 'valid': True, 'description': None},
{'id': 15, 'name': 'Time', 'alias': None, 'value': 2351.0, 'status': 1, 'valid': True, 'description': None}]},
{'datetime': '2013-01-01T00:10:00+02:00', 'channels': [
{'id': 1, 'name': 'Rain', 'alias': None, 'value': 0.0, 'status': 1, 'valid': True, 'description': None},
{'id': 2, 'name': 'WSmax', 'alias': None, 'value': 9.7, 'status': 1, 'valid': True, 'description': None},
{'id': 3, 'name': 'WDmax', 'alias': None, 'value': 42.0, 'status': 1, 'valid': True, 'description': None},
{'id': 4, 'name': 'WS', 'alias': None, 'value': 6.3, 'status': 1, 'valid': True, 'description': None},
{'id': 5, 'name': 'WD', 'alias': None, 'value': 55.0, 'status': 1, 'valid': True, 'description': None},
{'id': 6, 'name': 'STDwd', 'alias': None, 'value': 12.6, 'status': 1, 'valid': True, 'description': None},
{'id': 7, 'name': 'RH', 'alias': None, 'value': 54.0, 'status': 1, 'valid': True, 'description': None},
{'id': 8, 'name': 'TD', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 10, 'name': 'TDmax', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 11, 'name': 'TDmin', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 13, 'name': 'WS1mm', 'alias': None, 'value': 7.7, 'status': 1, 'valid': True, 'description': None},
{'id': 14, 'name': 'Ws10mm', 'alias': None, 'value': 6.3, 'status': 1, 'valid': True, 'description': None},
{'id': 15, 'name': 'Time', 'alias': None, 'value': 10.0, 'status': 1, 'valid': True, 'description': None}]},
{'datetime': '2013-01-01T00:20:00+02:00', 'channels': [
{'id': 1, 'name': 'Rain', 'alias': None, 'value': 0.0, 'status': 1, 'valid': True, 'description': None},
{'id': 2, 'name': 'WSmax', 'alias': None, 'value': 8.8, 'status': 1, 'valid': True, 'description': None},
{'id': 3, 'name': 'WDmax', 'alias': None, 'value': 42.0, 'status': 1, 'valid': True, 'description': None},
{'id': 4, 'name': 'WS', 'alias': None, 'value': 5.6, 'status': 1, 'valid': True, 'description': None},
{'id': 5, 'name': 'WD', 'alias': None, 'value': 55.0, 'status': 1, 'valid': True, 'description': None},
{'id': 6, 'name': 'STDwd', 'alias': None, 'value': 12.8, 'status': 1, 'valid': True, 'description': None},
{'id': 7, 'name': 'RH', 'alias': None, 'value': 55.0, 'status': 1, 'valid': True, 'description': None},
{'id': 8, 'name': 'TD', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 10, 'name': 'TDmax', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 11, 'name': 'TDmin', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 13, 'name': 'WS1mm', 'alias': None, 'value': 6.8, 'status': 1, 'valid': True, 'description': None},
{'id': 14, 'name': 'Ws10mm', 'alias': None, 'value': 6.3, 'status': 1, 'valid': True, 'description': None},
{'id': 15, 'name': 'Time', 'alias': None, 'value': 12.0, 'status': 1, 'valid': True, 'description': None}]},
{'datetime': '2013-01-01T00:30:00+02:00', 'channels': [
{'id': 1, 'name': 'Rain', 'alias': None, 'value': 0.0, 'status': 1, 'valid': True, 'description': None},
{'id': 2, 'name': 'WSmax', 'alias': None, 'value': 10.4, 'status': 1, 'valid': True, 'description': None},
{'id': 3, 'name': 'WDmax', 'alias': None, 'value': 60.0, 'status': 1, 'valid': True, 'description': None},
{'id': 4, 'name': 'WS', 'alias': None, 'value': 5.5, 'status': 1, 'valid': True, 'description': None},
{'id': 5, 'name': 'WD', 'alias': None, 'value': 54.0, 'status': 1, 'valid': True, 'description': None},
{'id': 6, 'name': 'STDwd', 'alias': None, 'value': 11.9, 'status': 1, 'valid': True, 'description': None},
{'id': 7, 'name': 'RH', 'alias': None, 'value': 55.0, 'status': 1, 'valid': True, 'description': None},
{'id': 8, 'name': 'TD', 'alias': None, 'value': 13.4, 'status': 1, 'valid': True, 'description': None},
{'id': 10, 'name': 'TDmax', 'alias': None, 'value': 13.5, 'status': 1, 'valid': True, 'description': None},
{'id': 11, 'name': 'TDmin', 'alias': None, 'value': 13.3, 'status': 1, 'valid': True, 'description': None},
{'id': 13, 'name': 'WS1mm', 'alias': None, 'value': 7.0, 'status': 1, 'valid': True, 'description': None},
{'id': 14, 'name': 'Ws10mm', 'alias': None, 'value': 5.6, 'status': 1, 'valid': True, 'description': None},
{'id': 15, 'name': 'Time', 'alias': None, 'value': 21.0, 'status': 1, 'valid': True, 'description': None}]},
{'datetime': '2013-01-01T00:40:00+02:00', 'channels': [
{'id': 1, 'name': 'Rain', 'alias': None, 'value': 0.0, 'status': 1, 'valid': True, 'description': None},
{'id': 2, 'name': 'WSmax', 'alias': None, 'value': 9.5, 'status': 1, 'valid': True, 'description': None},
{'id': 3, 'name': 'WDmax', 'alias': None, 'value': 61.0, 'status': 1, 'valid': True, 'description': None},
{'id': 4, 'name': 'WS', 'alias': None, 'value': 5.7, 'status': 1, 'valid': True, 'description': None},
{'id': 5, 'name': 'WD', 'alias': None, 'value': 52.0, 'status': 1, 'valid': True, 'description': None},
{'id': 6, 'name': 'STDwd', 'alias': None, 'value': 11.0, 'status': 1, 'valid': True, 'description': None},
{'id': 7, 'name': 'RH', 'alias': None, 'value': 55.0, 'status': 1, 'valid': True, 'description': None},
{'id': 8, 'name': 'TD', 'alias': None, 'value': 13.2, 'status': 1, 'valid': True, 'description': None},
{'id': 10, 'name': 'TDmax', 'alias': None, 'value': 13.3, 'status': 1, 'valid': True, 'description': None},
{'id': 11, 'name': 'TDmin', 'alias': None, 'value': 13.2, 'status': 1, 'valid': True, 'description': None},
{'id': 13, 'name': 'WS1mm', 'alias': None, 'value': 7.0, 'status': 1, 'valid': True, 'description': None},
{'id': 14, 'name': 'Ws10mm', 'alias': None, 'value': 5.7, 'status': 1, 'valid': True, 'description': None},
{'id': 15, 'name': 'Time', 'alias': None, 'value': 40.0, 'status': 1, 'valid': True, 'description': None}]}]
import json
import pandas as pd
from pandas.io.json import json_normalize
with open(r"Documents\dat.json") as data_file:
js_dict = json.load(data_file)
columns =list(json_normalize(js_dict["data"][0]["channels"])
["name"])
df = pd.DataFrame()
for row in js_dict["data"]:
val = json_normalize(row,record_path="channels").transpose().iloc[6]
new_val = pd.DataFrame(val).transpose().reset_index()
df = df.append(new_val)
print(df)
EDIT
我使用了另一个更基本的脚本,使用了较少的pandas函数,并大大缩短了时间,我想知道为什么pandas函数这么慢
from glob import glob
import json
import pandas as pd
from pandas.io.json import json_normalize
import time
import cProfile
def timing(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-
time1)*1000.0))
return ret
return wrap
@timing
def convert_json_panda_I(js_dict):
columns =list(json_normalize(js_dict[0]["channels"])["name"])
df = pd.DataFrame()
for row in js_dict:
val = json_normalize(row,record_path="channels").transpose().iloc[6]
new_val = pd.DataFrame(val).transpose().reset_index()
df = df.append(new_val)
return df
def decode_dict(dat):
row = []
for k, v in dat.items():
if k in 'datetime':
date = v
row.append(date)
elif k in 'channels':
for chanell in v:
row.append(chanell["value"])
return row
@timing
def convert_json_panda_II(json_dict):
df = pd.DataFrame([decode_dict(line) for line in json_dict])
return df
if __name__ == "__main__":
with open(r"C:\cygwin64\bin\zefat_bp.json") as data_file:
js_dict = json.load(data_file)
print("first version profile")
first_version = convert_json_panda_I(js_dict["data"])
print("second version profile")
second_version = cProfile.run('convert_json_panda_II(js_dict["data"])')
print(type(second_version))
print(second_version.head())
时间上的差异很大:
Connected to pydev debugger (build 181.4445.76)
convert_json_panda_I function took 2298914.500 ms
convert_json_panda_II function took 1389.219 ms
为什么使用熊猫函数这么慢?
答案 0 :(得分:1)
问题在于 df.append(new_val)
为每一行创建一个完整的新 Pandas 数据框(它复制前一个并只添加一个新行)。因此,对于 1,000,000
行,第一个版本将生成 1,000,000 个数据帧,每个数据帧平均 500,000 行。第二种方法只直接生成一个大数据帧。重点是:不要使用 Pandas 的 append
,使用 concat
。下面是一个例子:
import json
import pandas as pd
from pandas.io.json import json_normalize
with open(r"Documents\dat.json") as data_file:
js_dict = json.load(data_file)
columns =list(json_normalize(js_dict["data"][0]["channels"])
["name"])
rows = []
for row in js_dict["data"]:
val = json_normalize(row,record_path="channels").transpose().iloc[6]
rows.append(pd.DataFrame(val).transpose().reset_index())
df = pd.concat(rows)
print(df)