В качетсве формата этой работы мною был выбрано повествование через юпитерский ноутбук + текстовое резюме в виде этого маркдауна
Почему? Так как не будет устной защиты работы, то нужен формат максимально нагруженный информацией (ведь я не смогу дополнить по ходу защиты, тогда подошла бы преза, конечно)
В ноутбуке я подробно прокомментирую свои шаги, иллюстрируя, как я буду писать код на работе, чтобы с ним могли работать коллеги
В маркдауне будет резюме с основными выводами, на основании которых я бы готовил выступления для своих нетехнических коллег (для заказчиков)
Продакт-менеджер Василий попросил нас проанализировать завершенные уроки и ответить на следующие вопросы:
У нас есть 3 csvшные таблицы: assessments.csv; studentAssessment.csv; studentRegistration.csv
Этот файл содержит информацию об оценках в тесте. Обычно каждый предмет в семестре включает ряд тестов с оценками, за которыми следует заключительный экзаменационный тест (экзамен).
code_module --- идентификационный код предмета.
code_presentation --- семестр (Идентификационный код).
id_assessment --- тест (Идентификационный номер ассессмента).
assessment_type --- тип теста. Существуют три типа оценивания: оценка
преподавателя (TMA), компьютерная оценка (СМА), экзамен по курсу (Exam).
date --- информация об окончательной дате сдачи теста. Рассчитывается
как количество дней с момента начала семестра. Дата начала семестра
имеет номер 0 (ноль).
weight --- вес теста в % в оценке за курс. Обычно экзамены
рассматриваются отдельно и имеют вес 100%; сумма всех остальных оценок
составляет 100%.
- 7 предметов
- 4 семестра
- 206 форм контроля
- 3 вида контроля
- 11 пропусков в колонке date - всё соответствует экзаменам, возможно они не состоялись
- выше есть картинки распределений весов и дат #### Созданные переменные
as_nodate(df) - формы контроля без дедлайна
Файл содержит список предметов по семестрам.
code_module --- предмет (идентификационный код).
code_presentation --- семестр (идентификационный код).
module_presentation_length --- продолжительность семестра в днях.
- Количество предметов и семестров совпадает с предыдущей таблицей (это хорошо)
- У каждого предмета было от 2 до 4 запусков
- В каждом семестре было от 3 до 7 предметов
- Сумма дней в семестрах одного года больше 365 - видимо, это не классические вузовские семестры, а скорее какие-то потоки набора, какая-то часть двух семестров идёт параллельно
Этот файл содержит список предметов по семестрам. Если учащийся не отправляет работу на оценку, результат не записывается в таблицу.
id_assessment --- тест (идентификационный номер).
id_student --- идентификационный номер студента.
date_submitted --- дата сдачи теста студентом, измеряемая как
количество дней с начала семестра.
is_banked --- факт перезачета теста с прошлого семестра (иногда курсы
перезачитывают студентам, вернувшимся из академического отпуска).
score --- оценка учащегося в этом тесте. Диапазон составляет от 0 до
100. Оценка ниже 40 неудачная/неуспешная сдача теста. #### Созданные
переменные - abs_as (list) - формы, контроля оценок по которымм нет в
базе - no_date_but_taken (df) - формы контроля без дедлайна, которые
кто-то сдал
- Количество элементов оценивания меньше чем в таблице assessments на (18)
- Но все элементы оценивания есть в таблице assessments
- Есть элементы, которые никто не сдавал
- Есть элементы без дедлайна, которые кто-то сдал
- Есть те, кто сдал форму контроля раньше начала семестра... Причём это не те штуки, которые были перезачтены
- Распределение оценок смещено в сторону высоких оценок, с тремя модами (возможно это связано с тем, что если форма не сдавалась, то в таблицу она не заносилась, поэтому в таблице нет инфы о потенциально нулевых экзаменах)
Этот файл содержит информацию о времени, когда студент зарегистрировался для прохождения курса в семестре.
code_module --- предмет (идентификационный код).
code_presentation --- семестр (идентификационный код)
id_student --- идентификационный номер студента.
date_registration --- дата регистрации студента. Это количество дней,
измеренное от начала семестра (например, отрицательное значение -30
означает, что студент зарегистрировался на прохождение курса за 30 дней
до его начала).
date_unregistration --- дата отмены регистрации студента с предмета. У
студентов, окончивших курс, это поле остается пустым. #### Созданные
переменные - reg_count_module (df) - предметы и за-/отписавшиеся от
них - reg_count_pres (df) - модули и за-/отписавшиеся от них
- Все те-же 7 предметов и 4 семестра
- Есть тенденция у студентов записываться на курс не задолго до начала курса и отписываться скорее вначале курса
- Для решения задачи провести предварительное исследование данных и сформулируй, что должно считаться курсом. Обосновать свой выбор можно с помощью фактов сдачи экзаменов, распределения студентов и уникального идентификатора курса. ### Ответ: #### Курс - это уникальное сочетание предмета и семестра, которое есть в таблице courses и удовлетворяет условие, что есть хотя-бы один студент с этого курса не отчислился Этому утверждению удовлетворяют все курсы в таблице courses, но важно учесть, чтобы решение было более в общем случае Можно было бы его снять, однако я подумал, что для наших случаев для аналитики были бы более релевантны курс состоявшиеся Другие можно рассмотреть отдельно,если бы они были
- Есть курсы, где нет итоговой оценки (предмет GGG)
- Формы контроля не пересдавались ### Созданные переменные
ex_deadline(df) - курсы и количество экзаменов на них (всего/с дедлайнами)exes(list) - список экзаменовex_subm(df) - экзамены и количество сдавших эту работуfinished_courses(df) - курсы и количество студентов, которые их закончилиst_marks(df) - оценки, студенты, тип теста, семестр, предмет, веса, взвешенные оценкиst_marks0(df) - st_marks только с формами контроля с весом больше 0st_marks_exam(df) - оценки студентов по экзаменамst_marks_col(df) - оценки студентов по накопуst_marks_all(df) - оценки студентов по экзамену, накопу и итог (макс из предыдущих)
Сколько студентов успешно сдали только один курс? (Успешная сдача --- это зачёт по курсу на экзамене) (7 баллов). ### Ответ:
3802
Никто не сдал более двух экзаменов
st_passed_ex(df) - студенты и сданные экзаменыst_passed_ex_per_us(df) - студенты и количество сданных экзаменов
Выяви самый сложный и самый простой экзамен: найди курсы и экзамены в рамках курса, которые обладают самой низкой и самой высокой завершаемостью. (10 баллов) завершаемость = кол-во успешных экзаменов / кол-во всех попыток сдать экзамен ### Ответ:
Самый простой - курс семестра 2013B по предмету DDD (id экзамена 25340)
Самый сложный - курс семестра 2014B по предмету DDD (id экзамена 25361) ### Интересные наблюдения полученные в процессе поиска ответа:
- И самый простой, и самый сложный курсы по одному и тому-же предмету
- Даже у самого сложного курса процент закрытия > 83%
- Разница завершаемости между самым сложным и самым простым где-то 9%
tot(df) - попыток сдать каждый экзаменpas(df) - успеншных попыток сдать экзаменst_tried_to_pass_ex(df) - курс и процент сдачи
По каждому предмету определи средний срок сдачи экзаменов (под сдачей понимаем последнее успешное прохождение экзамена студентом). (7 баллов) ### Ответ:
Среднее время сдачи предмета CCC 239.3 дня - 2014B - 231.6; - 2014J - 244.4
Среднее время сдачи предмета DDD 238.0 дня - 2013B - 230.2; - 2013J - 239.5; - 2014B - 234.9; - 2014J - 242.8
ex_pas_dt_per_course(df) - среднее время сдачи экзамена по курсуex_pas_dt_per_subj(df) - среднее время сдачи экзамена по предмету
Выяви самые популярные предметы (ТОП-3) по количеству регистраций на них. А также предметы с самым большим оттоком (ТОП-3). (8 баллов)
отток = отписалось/записалось*100% (так учтём отличия в кол-во записавшихся) ### Ответ:
Топ-3 предметом по записи: - BBB - FFF - DDD
Топ-3 предметом по оттоку: - CCC - DDD - FFF
Топ-3 курсов по записи: - CCC 2014J - FFF 2014J - BBB 2014J
Топ-3 курсов по оттоку: - CCC 2014B - CCC 2014J - DDD 2014B
reg_count_module(df) - обновил, добавив оттокreg_count_module_pres(df) - аналог прошлой только с курсами
Используя pandas, в период с начала 2013 по конец 2014 выяви семестр с самой низкой завершаемостью курсов и самыми долгими средними сроками сдачи курсов. (15 баллов) ### Ответ: Семестр с самой низкой завершаемостью: 2013B (84%)
Семестр с самыми долгими средними сроками сдачи: 2014J (244 дня)
st_tried_to_pass_ex_sem(df) - семестр и процент сдачиex_pas_dt_per_sems(df) - семестр и среднее время сдачи
Часто для качественного анализа аудитории используют подходы, основанные на сегментации. Используя python, построй адаптированные RFM-кластеры студентов, чтобы качественно оценить свою аудиторию. В адаптированной кластеризации можешь выбрать следующие метрики: R - среднее время сдачи одного экзамена, F - завершаемость курсов, M - среднее количество баллов, получаемое за экзамен. Подробно опиши, как ты создавал кластеры. Для каждого RFM-сегмента построй границы метрик recency, frequency и monetary для интерпретации этих кластеров. Описание подхода можно найти тут (https://guillaume-martin.github.io/rfm-segmentation-with-python.html). (23 балла) ### Ответ: #### Я решил использовать другие метрики: - R - средний срок записи на курс (характеризует клиента, как покупателя) - F - средня средняя оценка за курс с учётом накопа (характеризует клиента, как ученика) - M - коэффициент прохождения курсов, отражающий количество курсов и долю завершения (говорит о нашей возможности заработать на этом клиенте)
Тому, что мы с метриками правильно поработали, свидетельствует схождение размеров датафреймов R и M
- least_motivated - купили в последний момент, завалили
- compulsive_buyers - купили сильно заранее, потом заыбли, завалили
- prepair_execute - заранее решили, хорошо сдали
- think_fast_execute - купили не сильно заранее, но серьёзно настроены были, хорошо сдали
- think_fast_hesitate - купили не сильно заранее, ходят по границе - усиленное внимание
- prepair_hesitate - заранее решили, ходят по границе - усиленное внимание
Среди кластеров есть такие потенциальный доход с которых резко ниже остальных 1 и 2 (как мы и предполагали), остальные примерно на одном уровне
Наибольший совокупный вклад в наш доход вносят представители 3 кластера, которые занимают 4 место по численности и по потенциальному доходу - 3 место
Наименьший совокупный вклад у кластеров 6 и 2, которые занимают по численности 6 и 3 места, и по потенциальному доходу - 1, 6
st_marks_all(df) - добавил среднюю оценкуst_marks_all_long(df) - длинный формат таблицы вышеst_marks_all_long_filter(df) - таблица выше, но без предмета GGGR(df) - id студента и метрика RF(df) - id студента и метрика Fcourse_length(df) - длина курсовunreg_length(df) - время выписывания студента и длина курсаM(df) - id студента и метрика Mquintiles(dict) - словарь с квантилямиRFM(df) - фрейм с id студента, баллами и сырыми RFM + сегментыRFM_share(df) - доли кластеровsegt_map(dict) - словарь с именами кластеровm_sum(df) - сумма M по кластерам
На основе анализа этих данных у меня вырисовывается следующая рекомендация:
Класс, который мог бы нам приносить больше всего дохода, самый малочисленный. Это класс тех, кто заранее записывается на наши курсы, но при это посредственно с ними справляется (но справялется), я думаю, что этот класс можно увеличить в объёме за счёт компульсивных покупателей, "прогрев" их в промежутке между записью на курс и его началом, удерживая их, когда спадёт раж покупки
Также я предлагаю использовать полностью наши формы контроля, позволить завершать курсы за счёт накопленных оценок (об этом подробнее сказано по ходу ответа на последний вопрос), это предотвратит ситуации, где мы упускаем курсы из виду, потому что там не было экзаменов (таких курсов большинство)
Также стоит обратить внимание на случай, когда у нас были отписавшиеся студенты, которые не записывались. Возможно там баг, который требует нашего внимания