Загрузите Json из сложного Csv / DataFrame, сохраните dtypes для MongoDB - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь собрать в дереве json запрашиваемую MongoDB из нескольких разрозненных файлов csv / excel.Данные часто неполны и связаны с идентификатором субъекта.

Пример данных ниже:

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'

Я бы хотел, чтобы вывод выглядел примерно так:

[
    {
        "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"
            }
        }
    }
]

У меня есть программа, которая помещает все это в правильную структуру, но, к сожалению, поскольку она использует DictReader от csv, кажется, что все переменные вводятся в виде строк, что затрудняет значимый запрос.Этот код ниже:

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()]

Как лучше всего решить эту проблему?Могу ли я преобразовать это для работы с фреймом данных и, надеюсь, сохранить dtypes?

Большое спасибо за любые советы.Новичок в Монго, просто пытаюсь получить что-то, что работает.

1 Ответ

0 голосов
/ 05 июня 2018

здесь не лучшее решение, но использование панд может быть полезным для сохранения типа значений, я не смотрел на эффективность кода, только на часть при чтении файла CSV, но вы можете сделать:

import pandas as pd
def solution(csv_filename):
    by_subject_id = defaultdict(lambda: {
        .
        .
    })

    df = pd.read_csv(csv_filename).fillna('')
    for row in df .iterrows():
        non_empty = {k: v for k, v in row[1].iteritems() if  v != ''}
        subject_id = non_empty['subid']  # must have to group by
        .
        .
        .

Я стараюсь изменить несколько строк, все остальное остается прежним.В конечном счете, если вы можете напрямую использовать очищенный DF вместо чтения файла CSV, было бы лучше.В противном случае вы можете добавить dtype= в read_csv (), например:

df = pd.read_csv(csv_filename,dtype={'subid':int, 'age':int}).fillna('')

добавить любой тип, который вы хотите иметь.

Надеюсь, это поможет вам

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...