写在前面
在金融风控领域,我们经常会使用到json格式的数据,例如运营商数据、第三方数据等。而这些数据往往不能直接作为结构化数据进行分析和建模。本文将介绍一种简单的、可复用性高的基于pandas的方法,可以快速地将json数据转化为结构化数据,以供分析和建模使用。
什么是jsonJSON(JavaScriptObject Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
用人话来说,json就是一种长得像嵌套字典的字符串。
数据被“{}”和“[]”层层包裹,需要“拆包”才能拿到我们需要的数据。例如下面这段数据,就是一种很常见的运营商json数据:
{'sign': '6E8127BDB7F66FE72FEF73B55FA47511',
'header': {'resp_time': '2019-03-20 17:25:23',
'ret_msg': '操作成功',
'version': '4.1',
'ret_code': '000000',
'req_time': '2019-03-20 17:25:23'},
'body': {'user_features': [{'user_feature_type': '0',
'last_modified_date': '2019-03-17'}],
'last_modified_time': '2019-03-17 13:51:41'}}
把它读进python里,它就是一个多层的字典。而我们需要做的就是把里面的内容给拿出来,转化成DataFrame或者其他的结构化格式。
怎么看json的结构
在解析json之前,我们必须先搞清楚它的结构。上面的例子是一个非常简单的json,它的结构很容易理解。但通常我们拿到的json数据会嵌套很多层,而且内容也非常多,看得人头晕眼花。这时候就需要一些工具来辅助我们进行分析。
Sublime text是一款非常好用的文本编辑器,支持绝大多数主流语言的语法高亮,使代码读起来更加省力,谁用谁说好。
Sublime text的下载链接:Download - Sublime Textwww.sublimetext.com
在安装Sublime text以后,我们还需要安装pretty json插件。这个插件可以帮助我们格式化json数据,使之结构更加清晰易读。
以笔者的mac电脑为例,在Sublime text中使用快捷键command+shift+p,打开面板,输入pci,选中“PackageControl: Install Package”并回车,然后输入pretty json找到插件并回车安装即可。安装完成之后,使用Sublime text打开要解析的json文件,然后按ctrl + command + J即可将json格式化,如下图所示:
格式化以后的json通过缩进来区分嵌套的层级,和python的代码块很像。这样,我们分析json的结构就方便了许多。
使用python解析json
python的json库可以将json读取为字典格式。首先,导入需要用到的库:
import pandas as pd
import json
然后,读取要解析的文件:
with open("/Users/test.json",'r') as load_f:
load_dict = json.load(load_f)
可以发现json一共有四层(最后有4个“}”),第一层只有一个key。我们可以先把它拆掉,然后转化成一个DataFrame:
load_dict = load_dict['mainData'] #拆第一层花括号
data_raw = pd.DataFrame(columns=load_dict.keys())
data_raw = data_raw.append(load_dict,ignore_index=True)
接下来,我们要做的就是把每一列中,格式为dict和list的内容进一步拆开。定义如下几个函数:
### 对嵌套的json进行拆包,每次拆一层
def json_to_columns(df,col_name):
for i in df[col_name][0].keys(): # 对dict的第一层key进行循环
list2=[j[i] for j in df[col_name]] # 存储对应上述key的value至列表推导式
df[i]=list2 # 存储到新的列中
df.drop(col_name,axis=1,inplace=True) # 删除原始列
return df
### 遍历整个dataframe,处理所有值类型为dict的列
def json_parse(df):
for i in df.keys():
if type(df[i][0])==dict and df[i][0]!={}:
df=json_to_columns(df,i) #调用上面的函数
return df
### 处理值类型为list的列,转换为dict
def list_parse(df):
for i in df.keys():
if type(df[i][0])==list and df[i][0]!=[]:
list1=[j[0] if j!=[] else np.nan for j in df[i]]
df[i]=list1
return df
每次调用json_parse函数和list_parse函数都可以“拆一层”,重复调用这两个函数,就可以把json里所有的内容都展开:字典的key变成列名,value变成值:
至此,json就成功地转化成了DataFrame格式。如果有多个json待解析,而他们的结构又完全一致,那么可以使用os模块结合for循环进行批量处理,把结果合并到同一个DataFrame当中。
总结一下,解析json的整体思路就是
①将json读入python转化为dict格式
②遍历dict中的每一个key,将key作为列名,对应的value作为值
③完成②以后,删除原始列,只保留拆开后的列
上述代码不一定能适用于所有的json文件,但思路可以作为参考。解析json之前还是需要先看结构,再决定如何解析。