【问题标题】:Creating Nested Json from CSV with incomplete rows从包含不完整行的 CSV 创建嵌套 Json
【发布时间】:2018-11-02 19:23:33
【问题描述】:

我已经将一些不同的 excel/csv 文件与 pandas 拼凑在一起,用于我正在尝试构建的数据库。我在这里看到了 few examples 从 csvs 创建嵌套 Jsons,虽然这些有助于部分复制我需要的东西,但它们最终都达不到要求。

相反,我的数据是逐步的,类似于this,其中数据由主题 ID #“连接”,但有关个人访问和样本的信息位于单独的行中,不相关的列带有“NaN”。

csv 格式:

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'

【问题讨论】:

    标签: python json mongodb pandas


    【解决方案1】:

    虽然我猜 SO 上的 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"
                }
            }
        }
    ]
    

    【讨论】:

    • 非常感谢。这对测试数据非常有效。不幸的是,我在真实场景中遇到了问题,我相信很大程度上是因为意外的 NaN。例如,Bob 的“dob”可能丢失或“date_entered”,它似乎把所有东西都扔掉了。
    • 添加了更准确的数据反映。给您带来的不便深表歉意。
    • 这就像一个魅力非常感谢你!我想让你知道,你以一种非常有意义的方式帮助了很多人。
    • 再次感谢您的所有帮助,一直忙于尝试将其扩展到更大的数据集。我注意到的一件事是,这似乎将所有内容都作为字符串返回。如果我想要年龄,比如说,成为一个整数,有什么方法可以解释这个吗?
    • 啊,这似乎是从 csv 读取的问题,它将所有内容读取为字符串。您不会碰巧知道将其转换为从数据帧中读取的好方法吗?
    猜你喜欢
    • 2013-06-07
    • 2021-11-01
    • 2017-10-04
    • 2021-02-20
    • 1970-01-01
    • 2017-07-07
    • 2014-03-26
    • 2019-03-29
    • 2021-10-02
    相关资源
    最近更新 更多