来自csv python的分层JSON
我有一个csv格式的数据集,如下所示:来自csv python的分层JSON,python,json,csv,hierarchy,Python,Json,Csv,Hierarchy,我有一个csv格式的数据集,如下所示: Name,code,count Adam,01,48 Bill,01,32 Chris,01,4 Carl,01.01,5 Dave,01.01,1 David,01.01,1 Eric,01.01.01,26 Earl,01.01.01.01,2 Frank,01.01.01.01,2 Greg,01.01.01.02,2 Harold,01.01.01.03,7 Ian,01.01.01.03,3 Jack,01.01.01.03,1 John,01.
Name,code,count
Adam,01,48
Bill,01,32
Chris,01,4
Carl,01.01,5
Dave,01.01,1
David,01.01,1
Eric,01.01.01,26
Earl,01.01.01.01,2
Frank,01.01.01.01,2
Greg,01.01.01.02,2
Harold,01.01.01.03,7
Ian,01.01.01.03,3
Jack,01.01.01.03,1
John,01.01.01.04,10
Kyle,01.01.01.04,2
Larry,01.01.03.01,3
Mike,01.01.03.01.01,45
Nick,01.01.03.01.01.01,1
Oliver,01.01.03.01.01.02,16
Paul,01.01.03.01.01.03,23
我想用python制作一个字典,其中“name”和“count”是键:值对(这很简单),但我想根据“code”编号组织一个层次结构。i、 e 01.01是01的孩子,我不确定如何迭代数据以实现这一点。我最终想对整个结构进行json转储,但让我失望的是如何构造层次结构。非常感谢您的帮助。我想您应该做一些标准的树结构,您可以访问树结构,使用路径访问时会自动创建缺少的节点 像这样的
class Node:
def __init__( self, parent=None ):
self.parent = parent
self.store = {}
self.children = {}
def create_child( self, child_name ):
self.children[ child_name ] = Node( self )
#ancestry_line is a list of names
def recursive_get_child( self, ancestry_line_names ):
if len(ancestry_line_names) == 0:
return self
else:
next_ancestor = ancestry_line_names[0]
other_ancestors = ancestry_line_names[1:]
if next_ancestor not in self.children:
self.create_child( next_ancestor )
return self.children[ next_ancestor ].recursive_get_child( other_ancestors )
您所需要做的就是创建一个根节点,并通过路径从中访问正确的节点
root = Node()
for name, code, count in some_data_iterator():
ancestry_line = code.split(".")
root.get( ancestry_line ).store[ name ] = count
然后,您可以在
节点
中创建一个方法,将节点结构转换为可在json
中转储的纯字典结构。下面的代码片段查找树的所有节点,而不实际创建一个。Python中的树和链表实现效率低下(Beazley)
在Python中实现树结构的一种简单而优雅的方法是使用递归:
您能否提供所需输出的示例?开始时有三个
01
元素-01.01
元素应如何适应层次结构?要将其分配给哪个元素?能否显示“层次结构”的一个片段。csv的某些行上最多显示5个其他字段?谢谢C Panda!这很有效。你能编辑你的回复,把这些行放进:import csv f=open(“somefile.csv”,“r”)……我想有些人需要them@miltonjbradley哪行bdw?我喜欢干净的代码。但是,它并没有使树结构显式化。@schwobasegll我知道这一点。因为我不知道继承人的样子。我不能给结果dict键赋予任何语义。我的python树将始终是一个dict
。但是我想知道它是什么样子。@CPanda我想如果你从内部的dicts
中删除多余的code
,只使用name:count
键值对,它会更干净。这将使结果在不丢失信息的情况下更不冗长。感谢您的回复。这只适用于一小部分人。我一使用整个文件,就出现了一个“太大而无法解包”的错误
from itertools import groupby
import csv
with open('csvfile.csv') as f:
reader = csv.DictReader(f)
groups = groupby(reader, key=lambda row: row['code'])
nodes = {code: {item['Name']: item['count'] for item in group} for code,group in groups}
{'01': {'Adam': '48', 'Bill': '32', 'Chris': '4'},
'01.01': {'Carl': '5', 'Dave': '1', 'David': '1'},
'01.01.01': {'Eric': '26'},
'01.01.01.01': {'Earl': '2', 'Frank': '2'},
'01.01.01.02': {'Greg': '2'},
'01.01.01.03': {'Harold': '7', 'Ian': '3', 'Jack': '1'},
'01.01.01.04': {'John': '10', 'Kyle': '2'},
'01.01.03.01': {'Larry': '3'},
'01.01.03.01.01': {'Mike': '45'},
'01.01.03.01.01.01': {'Nick': '1'},
'01.01.03.01.01.02': {'Oliver': '16'},
'01.01.03.01.01.03': {'Paul': '23'}}
import csv, json
from collections import defaultdict
def tree():
return defaultdict(tree)
d = tree()
with open('data.txt', 'rb') as f:
reader = csv.reader(f, delimiter=',')
for name, code, count in list(reader)[1:]:
path = code.split('.')
iter_node = d
for node in path:
iter_node = iter_node[node]
iter_node['values'][name] = count
print json.dumps(d, indent=2)
{
"01": {
"values": {
"Chris": "4",
"Bill": "32",
"Adam": "48"
},
"01": {
"values": {
"Dave": "1",
"Carl": "5",
"David": "1"
},
"03": {
"01": {
"01": {
"02": {
"values": {
"Oliver": "16"
}
},
"03": {
"values": {
"Paul": "23"
}
},
"01": {
"values": {
"Nick": "1"
}
},
"values": {
"Mike": "45"
}
},
"values": {
"Larry": "3"
}
}
},
"01": {
"values": {
"Eric": "26"
},
"02": {
"values": {
"Greg": "2"
}
},
"03": {
"values": {
"Harold": "7",
"Ian": "3",
"Jack": "1"
}
},
"01": {
"values": {
"Earl": "2",
"Frank": "2"
}
},
"04": {
"values": {
"John": "10",
"Kyle": "2"
}
}
}
}
}
}