Python 从包含不完整行的CSV创建嵌套Json
我已经用pandas拼凑了几个不同的excel/csv文件,作为我试图构建的数据库。我在这里看到了一个从CSV创建嵌套JSON的过程,虽然这些有助于部分复制我需要的东西,但它们最终还是做不到 与其说我的数据是平面的,不如说我的数据是逐步的,就像数据是由一个主题id#连接在一起的,但是关于个人访问和样本的信息是在单独的行上的,对于不相关的列是“NaN” csv格式:Python 从包含不完整行的CSV创建嵌套Json,python,json,mongodb,pandas,Python,Json,Mongodb,Pandas,我已经用pandas拼凑了几个不同的excel/csv文件,作为我试图构建的数据库。我在这里看到了一个从CSV创建嵌套JSON的过程,虽然这些有助于部分复制我需要的东西,但它们最终还是做不到 与其说我的数据是平面的,不如说我的数据是逐步的,就像数据是由一个主题id#连接在一起的,但是关于个人访问和样本的信息是在单独的行上的,对于不相关的列是“NaN” csv格式: subject_id,name,dob,gender,visit_date,date_entered,entered_by,samp
subject_id,name,dob,gender,visit_date,date_entered,entered_by,sample_id,collected_by,collection_date
1,Bob,1/1/00,M,,,,,,
1,,,,1/1/18,1/2/18,Sally,,,
1,,,,1/2/18,1/2/18,Tim,,,
1,,,,,,,XXX123,Sally,1/3/18
2,Mary,1/2/00,F,,,,,,
2,,,,1/3/18,1/4/18,Sally,,,
2,,,,,,,YYY456,Sally,1/5/18
2,,,,,,,ZZZ789,Tim,1/6/18
我试图得到如下输出:
{
'subject_id': '1'
'name': 'Bob',
'dob': '1/1/00',
'gender': 'M',
'visits': {
'1/1/18': {
'date_entered': '1/2/18',
'entered_by': 'Sally',
}
'1/2/18': {
'date_entered': '1/2/18',
'entered_by': 'Tim',
}
}
'samples': {
'XXX123': {
'collected_by': 'Sally',
'collection_date': '1/3/18',
}
}
}
{
'subject_id': '2'
'name': 'Mary',
'dob': '1/2/00',
'gender': 'F',
'visits': {
'1/3/18': {
'date_entered': '1/4/18',
'entered_by': 'Sally',
}
}
'samples': {
'YYY456': {
'collected_by': 'Sally',
'collection_date': '1/5/18',
}
'ZZZ789': {
'collected_by': 'Tim',
'collection_date': '1/6/18',
}
}
}
其中,访问和样本信息嵌套在更一般的信息下。这显然是我试图完成的一个简化数据集,但任何建议都将不胜感激
谢谢
编辑:
更准确地反映csv数据。不像原始示例那样精简或完整
'subid,firstvisit,name,contact,dob,gender,visitdate1,age,visitcategory,samplenumber,label_on_sample,completed_by
1,12/31/11,Bob,,12/31/00,Male,,,,,,
1,,,,,,12/31/15,17,Baseline Visit,,,
1,,,,,,12/31/16,18,Follow Up Visit,,,
1,,,,,,12/31/17,18,Follow Up Visit,,,
1,,,,12/31/00,Male,,17,,XXX123,1,Sally
2,1/1/12,,,1/1/01,Female,,,,,,
2,,,,,,1/1/11,10,Baseline Visit,,,
2,,,,,,1/1/12,11,Follow Up Visit,,,
2,,,,,,1/1/13,12,Follow Up Visit,,,
2,,,,,,1/1/14,13,Follow Up Visit,,,
2,,,,,,1/1/15,14,Follow Up Visit,,,
2,,,,1/1/01,Female,,15,,YYY456,2,
2,,,,1/1/01,Female,,15,,ZZZ789,2,Sally'
虽然我猜上的
pandas
向导有不同的方法,但这里有一种方法可以用纯Python实现示例输出(我使用Python 3.6.5编写了这个)
希望这能帮助你开始
编辑: 我修改了代码,希望能够解释提供的新示例csv数据。由于新csv的结构不完全相同,我不得不猜测一下最终的输出结构
from collections import defaultdict
from csv import DictReader
def solution(csv_filename):
by_subject_id = defaultdict(lambda: {
'name': None,
'dob': None,
'gender': None,
'visits': {},
'samples': {}
})
with open(csv_filename) as f:
dict_reader = DictReader(f)
for row in dict_reader:
non_empty = {k: v for k, v in row.items() if v}
subject_id = non_empty['subid'] # must have to group by
first_visit = non_empty.get('firstvisit') # optional
sample = non_empty.get('samplenumber') # optional
visit = non_empty.get('visitdate1') # optional
if first_visit:
by_subject_id[subject_id].update({
'name': non_empty.get('name'),
'dob': non_empty.get('dob'),
'gender': non_empty.get('gender')
})
elif visit:
by_subject_id[subject_id]['visits'][visit] = {
'age': non_empty.get('age'),
'visit_category': non_empty.get('visitcategory')
}
elif sample:
by_subject_id[subject_id]['samples'][sample] = {
'completed_by': non_empty.get('completed_by'),
'label_on_sample': non_empty.get('label_on_sample')
}
return [{'subject_id': k, **v} for k, v in by_subject_id.items()]
输出:
[
{
"subject_id": "1",
"name": "Bob",
"dob": "12/31/00",
"gender": "Male",
"visits": {
"12/31/15": {
"age": "17",
"visit_category": "Baseline Visit"
},
"12/31/16": {
"age": "18",
"visit_category": "Follow Up Visit"
},
"12/31/17": {
"age": "18",
"visit_category": "Follow Up Visit"
}
},
"samples": {
"XXX123": {
"completed_by": "Sally",
"label_on_sample": "1"
}
}
},
{
"subject_id": "2",
"name": null,
"dob": "1/1/01",
"gender": "Female",
"visits": {
"1/1/11": {
"age": "10",
"visit_category": "Baseline Visit"
},
"1/1/12": {
"age": "11",
"visit_category": "Follow Up Visit"
},
"1/1/13": {
"age": "12",
"visit_category": "Follow Up Visit"
},
"1/1/14": {
"age": "13",
"visit_category": "Follow Up Visit"
},
"1/1/15": {
"age": "14",
"visit_category": "Follow Up Visit"
}
},
"samples": {
"YYY456": {
"completed_by": null,
"label_on_sample": "2"
},
"ZZZ789": {
"completed_by": "Sally",
"label_on_sample": "2"
}
}
}
]
非常感谢。这对测试数据非常有效。不幸的是,我在现实生活中遇到了一些问题,我相信这主要是因为意外的南。例如,Bob的“dob”可能丢失或“date_entered”,这似乎是在抛开一切。添加了更准确的数据反映。对于给您带来的不便,我深表歉意。这很有魅力。非常感谢!我想让你知道,你在这方面帮助了很多人,非常有意义。再次感谢你的帮助,我一直在努力将此扩展到更大的数据集。我注意到的一点是,它似乎以字符串的形式返回所有内容。如果我想要年龄,比如说,成为一个整数,有什么方法可以解释这个问题吗?啊,从csv读入似乎是个问题,它将所有内容都作为字符串读取。你不会碰巧知道一个很好的方法来将其转换为从数据帧读取,是吗?