Собесов

ДКД МО ДЗМ: Excel/Python — анализ заболеваний COVID-19 по поликлиникам

PythonExcel и pandasЛёгкаяJunior

Условие

Дана выборка по заболеваниям (id заболевания, даты начала/выздоровления, id пациента, дата рождения, пол, тяжесть, медицинская организация). На отдельных вкладках Excel выполнить:

  1. Общее число пациентов и общее число заболеваний.
  2. Ежедневная динамика прироста инфекции.
  3. Распределение заболеваний по полу × возрастным категориям (0–17, 18–64, 65+) × тяжести; уязвимая группа.
  4. Рейтинг медорганизаций по заболевших / прикреплённое население.
  5. Аномальное поле и признак аномалии.
  6. Средняя продолжительность заболевания и от каких признаков она зависит.

Также — Python-блок (уникальные элементы, аббревиатура, разница в %, разделение на файлы).

Решение

Pandas-решение основной задачи

import pandas as pd
df = pd.read_excel('data.xlsx')
 
# 1) Общее число
total_patients = df['IDпациента'].nunique()
total_diseases = df['IDзаболевания'].nunique()
 
# 2) Ежедневная динамика
daily = df.groupby('Датаначалазаболевания').size().rename('cnt').reset_index()
daily['delta_pct'] = daily.cnt.pct_change() * 100
 
# 3) Распределение по полу/возрасту/тяжести
df['Возраст'] = (pd.to_datetime('2022-11-30') - pd.to_datetime(df.ДР)).dt.days // 365
df['ВозрКат'] = pd.cut(df.Возраст, bins=[0,17,64,200], labels=['0-17','18-64','65+'])
pivot = df.pivot_table(index=['Пол','ВозрКат'], columns='Тяжесть',
                       values='IDзаболевания', aggfunc='count', fill_value=0)
# Уязвимая группа = группа с макс долей "Средней"+"Тяжелой"
 
# 5) Аномалия — если есть пациент с ДР в будущем (5/13/17 → 2017, ребёнок 5 лет)
# или пол в нестандартном формате; проверяем пропуски и редкие значения
df.isna().sum()
df.Пол.value_counts()
 
# 6) Средняя продолжительность
df['Продолж'] = (pd.to_datetime(df.Датавыздоровления)
                  - pd.to_datetime(df.Датаначалазаболевания)).dt.days
df.groupby(['ВозрКат','Тяжесть']).Продолж.mean()

Python-задачи

# 1) Уникальные элементы списка
arr = [1,4,2,1,4,3,2,12,8,7,12]
unique = list(set(arr))
n = len(unique)
 
# 2) Аббревиатура
s = "Полис обязательного медицинского страхования"
abbr = "".join(w[0].upper() for w in s.split())
 
# 3) Разница в процентах между годами для возрастной группы
def find_mothers_age_diff(year1, year2, age_group):
    df = pd.read_csv('births-by-mothers-age.csv')
    df['share'] = df.value / df.groupby('year').value.transform('sum') * 100
    s1 = df.loc[(df.year==year1) & (df.age_group==age_group), 'share'].iloc[0]
    s2 = df.loc[(df.year==year2) & (df.age_group==age_group), 'share'].iloc[0]
    diff = s2 - s1
    print(f'Разница в группе {age_group} составляет {diff:+.2f}%. '
          f{year1} было {s1:.2f}%, в {year2} стало {s2:.2f}%')
 
# 4) Разделение на файлы
for clinic, sub in df.groupby('Медицинскаяорганизация'):
    sub.to_excel(f'{clinic}.xlsx', index=False)

Подводные камни

  1. Возраст по дате рождения: в датасете есть 5/13/17 — может быть либо 13.05.2017, либо 13.05.1917 — формат хранения американский (M/D/Y). Без явного формата → ошибки.
  2. «Прикреплённое население» — в отдельной справочной таблице; нужно JOIN (LEFT, иначе потеряем поликлиники без записей).
  3. Аномалия: чаще всего это пол с пустыми значениями или ID с лидирующими нулями (string vs int).
  4. Длительность заболевания: если Датавыздоровления пуста — пациент ещё болен; нельзя считать.

Эталонный ответ

1) nunique; 2) groupby даты + pct_change; 3) pivot_table с возр.группами; 4) JOIN с прикреплением, cases / population; 5) аномальное поле — пол / ДР; 6) средняя длительность по (возраст × тяжесть). Python: set, list comprehension с [0], разница долей, цикл groupby+to_excel.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти