【发布时间】:2018-08-14 22:53:51
【问题描述】:
我有以下 JSON 数据结构。我正在尝试将其放入 Pandas DataFrame。
pandas.io.json json_normalize 工作正常,除了“tunnels-in”和“tunnels-out”部分。这些是其中包含一些嵌套字典的列表。我已经尝试了我见过的几乎所有格式的 json_normalize 示例,但都没有成功。关于我能得到的工作如下。
json_normalize(json_dict['data']['viptela-oper-vpn']['dpi']['flows'])
只要我添加变量来定义额外的结构,我就无法克服错误。我研究了其他方法来做到这一点 - 记录在这里 - 这似乎确实有效,但它似乎没有处理任何垂直结构的概念。在这里,我们有一个流列表-我想将每个流展平为单独的列-其中每个流的值位于同一列的不同行中
https://towardsdatascience.com/flattening-json-objects-in-python-f5343c794b10
有谁知道使用 normalize 函数的方法,同时保留字典的嵌套列表?如您所见,并非每个流都有隧道输入/隧道输出。这是我自己试图将其弄平的另一个复杂因素。
非常感谢任何想法。
非常感谢,
数据结构
{
"data": {
"viptela-oper-vpn": {
"dpi": {
"flows": [
{
"vpn-id": 1,
"src-ip": "1.1.0.200",
"dst-ip": "1.3.0.200",
"src-port": 65369,
"dst-port": 1967,
"proto": "udp",
"application": "udp",
"family": "Network Service",
"active-since": "2018-02-28T22:51:54+00:00",
"packets": 2,
"octets": 132,
"tunnels-in": [
{
"index_me": 1,
"local-tloc": {
"ip": "1.1.1.104",
"color": "private2",
"encap": "ipsec"
},
"remote-tloc": {
"ip": "1.1.1.103",
"color": "private2",
"encap": "ipsec"
},
"packets": 1,
"octets": 80,
"start-time": "2018-02-28T22:51:54+00:00"
}
],
"tunnels-out": [
{
"index_me": 1,
"local-tloc": {
"ip": "1.1.1.104",
"color": "private2",
"encap": "ipsec"
},
"remote-tloc": {
"ip": "1.1.1.103",
"color": "mpls",
"encap": "ipsec"
},
"packets": 1,
"octets": 52,
"start-time": "2018-02-28T22:51:54+00:00"
}
]
},
{
"vpn-id": 1,
"src-ip": "1.1.0.200",
"dst-ip": "1.3.0.200",
"src-port": 65529,
"dst-port": 1967,
"proto": "udp",
"application": "udp",
"family": "Network Service",
"active-since": "2018-02-28T22:52:03+00:00",
"packets": 2,
"octets": 132,
"tunnels-in": [
{
"index_me": 1,
"local-tloc": {
"ip": "1.1.1.104",
"color": "private2",
"encap": "ipsec"
},
"remote-tloc": {
"ip": "1.1.1.103",
"color": "private2",
"encap": "ipsec"
},
"packets": 1,
"octets": 80,
"start-time": "2018-02-28T22:52:03+00:00"
}
],
"tunnels-out": [
{
"index_me": 1,
"local-tloc": {
"ip": "1.1.1.104",
"color": "private2",
"encap": "ipsec"
},
"remote-tloc": {
"ip": "1.1.1.103",
"color": "mpls",
"encap": "ipsec"
},
"packets": 1,
"octets": 52,
"start-time": "2018-02-28T22:52:03+00:00"
}
]
},
{
"vpn-id": 512,
"src-ip": "69.26.45.133",
"dst-ip": "198.19.200.2",
"src-port": 11895,
"dst-port": 22,
"proto": "tcp",
"application": "ssh",
"family": "Encrypted",
"active-since": "2018-02-28T22:42:15+00:00",
"packets": 1498,
"octets": 797954
},
{
"vpn-id": 512,
"src-ip": "198.19.200.2",
"dst-ip": "69.26.45.139",
"src-port": 514,
"dst-port": 514,
"proto": "udp",
"application": "syslog",
"family": "Application Service",
"active-since": "2018-02-28T22:50:59+00:00",
"packets": 8,
"octets": 2820
}
]
}
}
}
}
目前的功能
def myprint(file):
file_var = ''
with open(file) as f:
file_var = f.read()
extract_json_dict = re.compile('(\\n{\\n)(.*)(\\n}\\n)', re.DOTALL)
json_string = extract_json_dict.search(file_var).group(0)
json_dict = json.loads(json_string)
df = json_normalize(json_dict['data']['viptela-oper-vpn']['dpi']['flows'])
现在显示的列
['active-since', 'application', 'dst-ip', 'dst-port', 'family', 'octets', '数据包','proto','src-ip','src-port','tunnels-in','tunnels-out', 'vpn-id']
除了上面显示的列之外,我还想添加列
本质上,将具有列表作为值的那两列“展平”为附加列,并将每个流的值放在唯一的行中。
['tunnels-in_index_me', '隧道-in_remote-tloc_ip', '隧道-in_remote-tloc_color', '隧道-in_remote-tloc_encap', 'tunnels-out_remote-tloc_ip']
2018 年 3 月 8 日更新
对于其中包含字典列表的列,这似乎符合我的要求。但它需要流号的 [0] 标识符。不确定是否有人知道一种方法可以使其适用于所有流程 - 一次不是一个。如果可以做到这一点,我应该能够根据索引号进行连接或合并。使用单个 json_normalize 行来完成整个事情会更好——但除了 [0] 的问题之外,这似乎还有一个额外的问题,即并非所有流号都有嵌套的字典列表。我会继续尝试这个,但任何想法都值得赞赏。
json_normalize(json_dict['data']['viptela-oper-vpn']['dpi']['flows'][0]['tunnels-in'])
【问题讨论】: