Kelevra_Slevin

Project_2

Dec 26th, 2022 (edited)
1,039
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 42.52 KB | None | 0 0
  1. # Исследование надежности заемщиков
  2.  
  3. Это первая часть проекта, она будет проверена автоматически. Вторую часть проверит ревьюер.
  4.  
  5. ## Откройте таблицу и изучите общую информацию о данных
  6.  
  7. **Задание 1. Импортируйте библиотеку pandas. Считайте данные из csv-файла в датафрейм и сохраните в переменную `data`. Путь к файлу:**
  8.  
  9. `/datasets/data.csv`
  10.  
  11. import pandas as pd# импортируйте библиотеку pandas
  12.  
  13. data = pd.read_csv('/datasets/data.csv')# прочитайте csv-файл
  14.  
  15. **Задание 2. Выведите первые 20 строчек датафрейма `data` на экран.**
  16.  
  17. data.head(20)# ваш код здесь
  18.  
  19. **Задание 3. Выведите основную информацию о датафрейме с помощью метода `info()`.**
  20.  
  21. data.info()# ваш код здесь
  22.  
  23. ## Предобработка данных
  24.  
  25. ### Удаление пропусков
  26.  
  27. **Задание 4. Выведите количество пропущенных значений для каждого столбца. Используйте комбинацию двух методов.**
  28.  
  29. data.isna().sum()# ваш код здесь
  30.  
  31. **Задание 5. В двух столбцах есть пропущенные значения. Один из них — `days_employed`. Пропуски в этом столбце вы обработаете на следующем этапе. Другой столбец с пропущенными значениями — `total_income` — хранит данные о доходах. На сумму дохода сильнее всего влияет тип занятости, поэтому заполнить пропуски в этом столбце нужно медианным значением по каждому типу из столбца `income_type`. Например, у человека с типом занятости `сотрудник` пропуск в столбце `total_income` должен быть заполнен медианным доходом среди всех записей с тем же типом.**
  32.  
  33. for i in data['income_type'].unique():
  34.     data.loc[(data['income_type'] == i) & (data['total_income'].isna()),'total_income']=\
  35.     data.loc[(data['income_type'] == i), 'total_income'].median()
  36.  
  37. ### Обработка аномальных значений
  38.  
  39. **Задание 6. В данных могут встречаться артефакты (аномалии) — значения, которые не отражают действительность и появились по какой-то ошибке. Таким артефактом будет отрицательное количество дней трудового стажа в столбце `days_employed`. Для реальных данных это нормально. Обработайте значения в этом столбце: замените все отрицательные значения положительными с помощью метода `abs()`.**
  40.  
  41. data['days_employed'] = data['days_employed'].abs()
  42.  
  43. **Задание 7. Для каждого типа занятости выведите медианное значение трудового стажа `days_employed` в днях.**
  44.  
  45. data.groupby('income_type')['days_employed'].median()
  46.  
  47. У двух типов (безработные и пенсионеры) получатся аномально большие значения. Исправить такие значения сложно, поэтому оставьте их как есть. Тем более этот столбец не понадобится вам для исследования.
  48.  
  49. **Задание 8. Выведите перечень уникальных значений столбца `children`.**
  50.  
  51. data['children'].unique()# ваш код здесь
  52.  
  53. **Задание 9. В столбце `children` есть два аномальных значения. Удалите строки, в которых встречаются такие аномальные значения из датафрейма `data`.**
  54.  
  55. data = data[(data['children'] != -1) & (data['children'] != 20)]
  56.  
  57. **Задание 10. Ещё раз выведите перечень уникальных значений столбца `children`, чтобы убедиться, что артефакты удалены.**
  58.  
  59. data['children'].unique()# ваш код здесь
  60.  
  61. ### Удаление пропусков (продолжение)
  62.  
  63. **Задание 11. Заполните пропуски в столбце `days_employed` медианными значениями по каждому типу занятости `income_type`.**
  64.  
  65. for i in data['income_type'].unique():
  66.     data.loc[(data['income_type'] == i) & (data['days_employed'].isna()),'days_employed']=\
  67.     data.loc[(data['income_type'] == i), 'days_employed'].median()# ваш код здесь
  68.  
  69. **Задание 12. Убедитесь, что все пропуски заполнены. Проверьте себя и ещё раз выведите количество пропущенных значений для каждого столбца с помощью двух методов.**
  70.  
  71. data.isna().sum()# ваш код здесь
  72.  
  73. ### Изменение типов данных
  74.  
  75. **Задание 13. Замените вещественный тип данных в столбце `total_income` на целочисленный с помощью метода `astype()`.**
  76.  
  77. data['total_income'] = data['total_income'].astype(int)# ваш код здесь
  78.  
  79. ### Обработка дубликатов
  80.  
  81. **Задание 14. Обработайте неявные дубликаты в столбце `education`. В этом столбце есть одни и те же значения, но записанные по-разному: с использованием заглавных и строчных букв. Приведите их к нижнему регистру.**
  82.  
  83. data['education'] = data['education'].str.lower()# ваш код здесь
  84.  
  85. **Задание 15. Выведите на экран количество строк-дубликатов в данных. Если такие строки присутствуют, удалите их. Сбрасывать индексы после удаления строк дубликатов с помощью `reset_index(drop=True)` здесь не требуется.**
  86.  
  87. data.duplicated().sum()# посчитайте дубликаты
  88.  
  89. data.drop_duplicates()# удалите дубликаты
  90.  
  91. ### Категоризация данных
  92.  
  93. **Задание 16. На основании диапазонов, указанных ниже, создайте в датафрейме `data` столбец `total_income_category` с категориями:**
  94.  
  95. - 030000 — `'E'`;
  96. - 3000150000 — `'D'`;
  97. - 50001200000 — `'C'`;
  98. - 2000011000000 — `'B'`;
  99. - 1000001 и выше — `'A'`.
  100.  
  101.  
  102. **Например, кредитополучателю с доходом 25000 нужно назначить категорию `'E'`, а клиенту, получающему 235000, — `'B'`. Используйте собственную функцию с именем `categorize_income()` и метод `apply()`.**
  103.  
  104. def categorize_income(row):
  105.     if row < 30000:
  106.         return 'E'
  107.     elif 30001 <= row <= 50000:
  108.         return 'D'
  109.     elif 50001 <= row <= 200000:
  110.         return 'C'
  111.     elif 200001 <= row <= 1000000:
  112.         return 'B'
  113.     elif row >= 1000001:
  114.         return 'A'# создайте функцию categorize_income()
  115.  
  116. data['total_income_category'] = data['total_income'].apply(categorize_income)
  117. # примените функцию методом apply()
  118.  
  119. **Задание 17. Выведите на экран перечень уникальных целей взятия кредита из столбца `purpose`.**
  120.  
  121. data['purpose'].unique()# ваш код здесь
  122.  
  123. **Задание 18. Создайте функцию, которая на основании данных из столбца `purpose` сформирует новый столбец `purpose_category`, в который войдут следующие категории:**
  124.  
  125. - `'операции с автомобилем'`,
  126. - `'операции с недвижимостью'`,
  127. - `'проведение свадьбы'`,
  128. - `'получение образования'`.
  129.  
  130. **Например, если в столбце `purpose` находится подстрока `'на покупку автомобиля'`, то в столбце `purpose_category` должна появиться строка `'операции с автомобилем'`.**
  131.  
  132. **Используйте собственную функцию с именем `categorize_purpose()` и метод `apply()`. Изучите данные в столбце `purpose` и определите, какие подстроки помогут вам правильно определить категорию.**
  133.  
  134. def categorize_purpose(row):
  135.     try:
  136.         if 'автом' in row:
  137.             return 'операции с автомобилем'
  138.         elif 'жил' in row or 'недвиж' in row:
  139.             return 'операции с недвижимостью'
  140.         elif 'свад' in row:
  141.             return 'проведение свадьбы'
  142.         elif 'образов' in row:
  143.             return 'получение образования'
  144.     except:
  145.         return 'нет категории'
  146. data['purpose_category'] = data['purpose'].apply(categorize_purpose)
  147.     # создайте функцию categorize_purpose()
  148.  
  149. data['purpose_category'] = data['purpose'].apply(categorize_purpose)# примените функцию методом apply()
  150.  
  151.  
  152. <h1> Комментарий ревьюера </h1>
  153.  
  154. Кирилл, привет!
  155.  
  156. Меня зовут Олег Михеев, и я буду проверять твой проект. Предлагаю общаться на "ты", но если тебе будет некомфортно, обязательно сообщи и мы перейдем на "вы". Моя главная цель - не указать на твои ошибки, а поделиться опытом и подготовить тебя к работе аналитиком. Увидев у тебя ошибку, я постараюсь указать на её наличие и дам возможность найти и самостоятельно исправить её.
  157.  
  158. В проверке проекта я буду использовать разные цвета для обозначения комментариев. Например:
  159.  
  160. <br/>
  161.  
  162. <div class="alert alert-success">
  163. <h3> Комментарий ревьюера <a class="tocSkip"> </h3>
  164.  
  165. <b>Все отлично!✔️:</b> Решение на отдельном шаге является полностью правильным.
  166. </div>
  167.  
  168. <br/>
  169.  
  170. <div class="alert alert-warning">
  171.     <h3> Комментарий ревьюера <a class="tocSkip"> </h3>
  172.  
  173. <b>Некоторые замечания и рекомендации⚠️:</b> Когда решение на отдельном шаге станет лучше, если внести небольшие коррективы.
  174. </div>
  175.  
  176.  
  177. <br/>
  178. <div class="alert alert-block alert-danger">
  179. <h3> Комментарий ревьюера <a class="tocSkip"></h3>
  180.  
  181.    
  182. <b>На доработку❌:</b>
  183.  Решение на отдельном шаге требует существенной переработки, без которого я не смогу принять проект.
  184. </div>
  185.    
  186.  
  187. Если вносишь изменения в проект, указывай, пожалуйста, это в своих комментариях. Будет удобно, если обозначишь их заметным цветом. Например, вот так:
  188.        
  189. <div class="alert alert-block alert-info">
  190.    
  191. <h3> Комментарий студента  <a class="tocSkip"></h3>
  192.    
  193. Можешь кликнуть сюда два раза и скопировать код комментария. Также если что-то непонятно или остались вопросы по ревью, обязательно пиши.
  194.    
  195. </div>
  196.    
  197. Пожалуйста, не удаляй и не перемещай мои комментарии, чтобы не произошло путаницы, и я мог быстрее проверить проект.
  198.  
  199. <br/>
  200.  
  201. <div style="border:solid Chocolate 2px; padding: 40px">
  202.  
  203. **Общий вывод после второй итерации**
  204.  
  205. Спасибо за твой проект! Уверен, ты приложил все усилия для выполнения задания, а выводы показывают, что ты быстро осваиваешь материал.
  206.  
  207. **Отмечу отдельные положительные моменты проекта**:
  208.  
  209. * Ты прошёлся по всем этапам выполнения задания и справился почти со всем
  210. * У тебя аккуратный и чистый код
  211. * Ты пишешь качественные подробные выводы
  212.  
  213.  
  214. **Что нужно сделать, чтобы я мог принять проект**:
  215.    
  216. * Дописать финальный вывод основными идеями из промежуточных выводов
  217.    
  218.  
  219. **Успехов! Жду проект на повторное ревью!**
  220.  
  221. <div style="border:solid Chocolate 2px; padding: 40px">
  222.  
  223. **Общий вывод по проекту v3**
  224.  
  225. У тебя получилась хороший проект с качественными выводами. Рекомендую только более детально описывать финальный вывод, рассказывая о полученных результатах анализа, группах, которые были рассмотрены, числах, которые можно пустить в работу.
  226.    
  227.  
  228. **Проект принимаю. Успехов в дальнейшем обучении!**
  229.  
  230. <div class="alert alert-block alert-danger">
  231. <h3> Комментарий ревьюера <a class="tocSkip"></h3>
  232.  
  233.    
  234. <b>На доработку❌:</b>
  235.     В проекте увидел ответ только на один вопрос. У тебя возникли какие-то сложности, нужно подсказать, с чего начать? Или ты случайно отправил проект?
  236.  
  237. Если это технические проблемы - напиши в техподдрежку и куратору.
  238.  
  239. Если ты не знаешь с чего начать - можно задать вопрос преподавателю по проектам в чате slack. А можешь написать вопрос в проекте и опять отправить на проверку - так я смогу тебе ответить.
  240.    
  241. Если случайно отправил проект, ответь, пожалуйста, на оставшиеся 5 вопросов и напиши вывод, учитывающий все промежуточные выводы.
  242. </div>
  243.  
  244. <div class="alert alert-block alert-info">
  245.    
  246. <h3> Комментарий студента  <a class="tocSkip"></h3>
  247.    
  248. Приветствую, Олег! Почему-то не сохранились данные... При отправке все строчки были на месте. Сейчас попробую продублировать. Комментарий по оптимизации кода учел, просто это первый проект.. Старался сделать максимально понятно для самого себя, поэтому всё так подробно)
  249.    
  250. </div>
  251.  
  252. <div class="alert alert-success">
  253. <h3> Комментарий ревьюера v2<a class="tocSkip"> </h3>
  254.  
  255. <b>Все отлично!✔️:</b> Хорошо, понял. Если работаешь локально, старайся перепроверять всё ли на месте и всё ли работает, когда переносишь на платформу.
  256.  
  257. # Исследование надежности заемщиков
  258.  
  259.  
  260. Во второй части проекта вы выполните шаги 3 и 4. Их вручную проверит ревьюер.
  261. Чтобы вам не пришлось писать код заново для шагов 1 и 2, мы добавили авторские решения в ячейки с кодом.
  262.  
  263.  
  264.  
  265. ## Откройте таблицу и изучите общую информацию о данных
  266.  
  267. **Задание 1. Импортируйте библиотеку pandas. Считайте данные из csv-файла в датафрейм и сохраните в переменную `data`. Путь к файлу:**
  268.  
  269. `/datasets/data.csv`
  270.  
  271. import pandas as pd
  272.  
  273. try:
  274.     data = pd.read_csv('/datasets/data.csv')
  275. except:
  276.     data = pd.read_csv('https://code.s3.yandex.net/datasets/data.csv')
  277.  
  278. **Задание 2. Выведите первые 20 строчек датафрейма `data` на экран.**
  279.  
  280. data.head(20)
  281.  
  282. **Задание 3. Выведите основную информацию о датафрейме с помощью метода `info()`.**
  283.  
  284. data.info()
  285.  
  286. ## Предобработка данных
  287.  
  288. ### Удаление пропусков
  289.  
  290. **Задание 4. Выведите количество пропущенных значений для каждого столбца. Используйте комбинацию двух методов.**
  291.  
  292. data.isna().sum()
  293.  
  294. **Задание 5. В двух столбцах есть пропущенные значения. Один из них — `days_employed`. Пропуски в этом столбце вы обработаете на следующем этапе. Другой столбец с пропущенными значениями — `total_income` — хранит данные о доходах. На сумму дохода сильнее всего влияет тип занятости, поэтому заполнить пропуски в этом столбце нужно медианным значением по каждому типу из столбца `income_type`. Например, у человека с типом занятости `сотрудник` пропуск в столбце `total_income` должен быть заполнен медианным доходом среди всех записей с тем же типом.**
  295.  
  296. for t in data['income_type'].unique():
  297.     data.loc[(data['income_type'] == t) & (data['total_income'].isna()), 'total_income'] = \
  298.     data.loc[(data['income_type'] == t), 'total_income'].median()
  299.  
  300. ### Обработка аномальных значений
  301.  
  302. **Задание 6. В данных могут встречаться артефакты (аномалии) — значения, которые не отражают действительность и появились по какой-то ошибке. таким артефактом будет отрицательное количество дней трудового стажа в столбце `days_employed`. Для реальных данных это нормально. Обработайте значения в этом столбце: замените все отрицательные значения положительными с помощью метода `abs()`.**
  303.  
  304. data['days_employed'] = data['days_employed'].abs()
  305.  
  306. **Задание 7. Для каждого типа занятости выведите медианное значение трудового стажа `days_employed` в днях.**
  307.  
  308. data.groupby('income_type')['days_employed'].agg('median')
  309.  
  310. У двух типов (безработные и пенсионеры) получатся аномально большие значения. Исправить такие значения сложно, поэтому оставьте их как есть. Тем более этот столбец не понадобится вам для исследования.
  311.  
  312. **Задание 8. Выведите перечень уникальных значений столбца `children`.**
  313.  
  314. data['children'].unique()
  315.  
  316. **Задание 9. В столбце `children` есть два аномальных значения. Удалите строки, в которых встречаются такие аномальные значения из датафрейма `data`.**
  317.  
  318. data = data[(data['children'] != -1) & (data['children'] != 20)]
  319.  
  320. **Задание 10. Ещё раз выведите перечень уникальных значений столбца `children`, чтобы убедиться, что артефакты удалены.**
  321.  
  322. data['children'].unique()
  323.  
  324. ### Удаление пропусков (продолжение)
  325.  
  326. **Задание 11. Заполните пропуски в столбце `days_employed` медианными значениями по каждого типа занятости `income_type`.**
  327.  
  328. for t in data['income_type'].unique():
  329.     data.loc[(data['income_type'] == t) & (data['days_employed'].isna()), 'days_employed'] = \
  330.     data.loc[(data['income_type'] == t), 'days_employed'].median()
  331.  
  332. **Задание 12. Убедитесь, что все пропуски заполнены. Проверьте себя и ещё раз выведите количество пропущенных значений для каждого столбца с помощью двух методов.**
  333.  
  334. data.isna().sum()
  335.  
  336. ### Изменение типов данных
  337.  
  338. **Задание 13. Замените вещественный тип данных в столбце `total_income` на целочисленный с помощью метода `astype()`.**
  339.  
  340. data['total_income'] = data['total_income'].astype(int)
  341.  
  342. ### Обработка дубликатов
  343.  
  344. **Задание 14. Обработайте неявные дубликаты в столбце `education`. В этом столбце есть одни и те же значения, но записанные по-разному: с использованием заглавных и строчных букв. Приведите их к нижнему регистру. Проверьте остальные столбцы.**
  345.  
  346. data['education'] = data['education'].str.lower()
  347.  
  348. **Задание 15. Выведите на экран количество строк-дубликатов в данных. Если такие строки присутствуют, удалите их.**
  349.  
  350. data.duplicated().sum()
  351.  
  352. data = data.drop_duplicates()
  353.  
  354. ### Категоризация данных
  355.  
  356. **Задание 16. На основании диапазонов, указанных ниже, создайте в датафрейме `data` столбец `total_income_category` с категориями:**
  357.  
  358. - 030000 — `'E'`;
  359. - 3000150000 — `'D'`;
  360. - 50001200000 — `'C'`;
  361. - 2000011000000 — `'B'`;
  362. - 1000001 и выше — `'A'`.
  363.  
  364.  
  365. **Например, кредитополучателю с доходом 25000 нужно назначить категорию `'E'`, а клиенту, получающему 235000, — `'B'`. Используйте собственную функцию с именем `categorize_income()` и метод `apply()`.**
  366.  
  367. def categorize_income(income):
  368.     try:
  369.         if 0 <= income <= 30000:
  370.             return 'E'
  371.         elif 30001 <= income <= 50000:
  372.             return 'D'
  373.         elif 50001 <= income <= 200000:
  374.             return 'C'
  375.         elif 200001 <= income <= 1000000:
  376.             return 'B'
  377.         elif income >= 1000001:
  378.             return 'A'
  379.     except:
  380.         pass
  381.  
  382. data['total_income_category'] = data['total_income'].apply(categorize_income)
  383. data
  384.  
  385. **Задание 17. Выведите на экран перечень уникальных целей взятия кредита из столбца `purpose`.**
  386.  
  387. data['purpose'].unique()
  388.  
  389. **Задание 18. Создайте функцию, которая на основании данных из столбца `purpose` сформирует новый столбец `purpose_category`, в который войдут следующие категории:**
  390.  
  391. - `'операции с автомобилем'`,
  392. - `'операции с недвижимостью'`,
  393. - `'проведение свадьбы'`,
  394. - `'получение образования'`.
  395.  
  396. **Например, если в столбце `purpose` находится подстрока `'на покупку автомобиля'`, то в столбце `purpose_category` должна появиться строка `'операции с автомобилем'`.**
  397.  
  398. **Используйте собственную функцию с именем `categorize_purpose()` и метод `apply()`. Изучите данные в столбце `purpose` и определите, какие подстроки помогут вам правильно определить категорию.**
  399.  
  400. def categorize_purpose(row):
  401.     try:
  402.         if 'автом' in row:
  403.             return 'операции с автомобилем'
  404.         elif 'жил' in row or 'недвиж' in row:
  405.             return 'операции с недвижимостью'
  406.         elif 'свад' in row:
  407.             return 'проведение свадьбы'
  408.         elif 'образов' in row:
  409.             return 'получение образования'
  410.     except:
  411.         return 'нет категории'
  412.  
  413. data['purpose_category'] = data['purpose'].apply(categorize_purpose)
  414.  
  415. ### Шаг 3. Исследуйте данные и ответьте на вопросы
  416.  
  417. #### 3.1 Есть ли зависимость между количеством детей и возвратом кредита в срок?
  418.  
  419. #группировка данных по количеству детей и факту задолженности. Через функцию "agg" передаем кол-во значений, сумму и среднюю
  420. debtor_with_children = data.groupby('children')['debt'].agg(['count', 'sum', 'mean'])
  421.  
  422. debtor_with_children = debtor_with_children.sort_values(by='mean',ascending=False)# сортировка для наглядности
  423.  
  424. debtor_with_children['mean'] = debtor_with_children['mean'].apply('{:2%}'.format)#приводим в божеский вид
  425.  
  426. debtor_with_children = debtor_with_children.rename(columns={'count':'Заемщики','sum':'Должники','mean':'Процент должников'})#
  427.  
  428. debtor_with_children
  429.  
  430. # Вывод
  431.  
  432.     При анализе данных можно сделать вывод, что количество детей у заемщика влияет на его платежную дисциплину. Заемщики с одним и двумя детьми допускают просрочку платежа чаще, чем бездетные. Возможно, это объясняется тем, что заемщики с детьми имеют больше незапланированных финансовых расходов.
  433.     Разница в 1.7-1.9% может не показаться большой, однако не стоит забывать, что банковская сфера может оперировать цифрами в сотни миллионов рублей, а просроченные платежи по кредиту вынуждают банк формировать дополнительные денежные резервы, что снижает финансовый оборот, соответственно возникает риск упущенной выгоды. Таким образом, клиенты не имеющие детей, имеют более высокие шансы на положительный результат скоринга.
  434.      
  435.  
  436.     *При нахождении ответа не учитывались заемщики с четырьмя и пятью детьми, т.к. их количество в общей массе данных чрезвычайно мало. Также заемщики с тремя детьми будут мало информативны с точки зрения репрезентативности.
  437.  
  438. <div class="alert alert-success">
  439. <h3> Комментарий ревьюера <a class="tocSkip"> </h3>
  440.  
  441. <b>Все отлично!✔️:</b> Супер, согласен с твоей интерпретацией, дети действительно могут налагать непредвиденные расходы. Здорово, что обращаешь внимание на размер групп.
  442. Твой код можно было сделать компактнее. Вот, как сделал бы я:
  443.    
  444.     debtor_with_children = data.groupby('children')['debt'].agg(['count', 'sum', 'mean'])\
  445.         .sort_values(by='mean',ascending=False)\
  446.         .rename(columns={'count':'Заемщики','sum':'Должники','mean':'Процент должников'})
  447.  
  448. Обратный слэш позволяет не учитывать перенос на новую строку, поэтому код будет работать. Все методы выполняются последовательно.
  449. </div>
  450.  
  451. #### 3.2 Есть ли зависимость между семейным положением и возвратом кредита в срок?
  452.  
  453. debtor_family_status = data.groupby('family_status')['debt'].agg(['count', 'sum', 'mean'])
  454.  
  455. debtor_family_status['mean'] = debtor_family_status['mean'].apply('{:2%}'.format)
  456.  
  457. debtor_family_status = debtor_family_status.sort_values(by='mean',ascending=False)
  458.  
  459. debtor_family_status = debtor_family_status.rename(columns={'count':'Заемщики','sum':'Должники','mean':'Процент должников'})
  460.  
  461. debtor_family_status
  462.  
  463. # Вывод
  464.  
  465.  
  466. При ответе на вопрос о корреляции семейного положения заёмщика и потенциально просроченного платежа, можно сделать следующие выводы.
  467.  
  468. Заёмщики, не состоящие в официальном браке, более склонны к появлению просроченных платежей. Видимо, это можно объяснить более низким уровнем финансовой ответственности,т.к. меньше официальных обязательств. Заёмщики, поставившие штамп в паспорт, напротив, относятся к погашению кредита более сознательно(скорее всего, строгая жена попалась). И наконец, самая ответственная категория - заещики, которые вкусили прелести супружеской жизни и теперь живут в одиночку. Очевидно понимают, что рассчитывать не на кого и минимизируют риск просроченного платежа.
  469.  
  470. <div class="alert alert-success">
  471. <h3> Комментарий ревьюера v2<a class="tocSkip"> </h3>
  472.  
  473. <b>Все отлично!✔️:</b> Да, абсолютно согласен, один из вариантов интерпретации действительно состоит в том, что брак дисциплинирует. А может быть в официальный брак вступают уже более зрелые и ответственные люди.
  474. </div>
  475.  
  476. #### 3.3 Есть ли зависимость между уровнем дохода и возвратом кредита в срок?
  477.  
  478. debtor_income_category = data.groupby('total_income_category')['debt'].agg(['count', 'sum', 'mean'])
  479.  
  480. debtor_income_category['mean'] = debtor_income_category['mean'].apply('{:2%}'.format)
  481.  
  482. debtor_income_category = debtor_income_category.sort_values(by='mean',ascending=False)
  483.  
  484. debtor_income_category = debtor_income_category.rename(columns={'count':'Заемщики','sum':'Должники','mean':'Процент должников'})
  485.  
  486. debtor_income_category
  487.  
  488. # Вывод
  489.  
  490. Категории заемщиков с более низким уровнем дохода ('E' и 'D') можно не учитывать при анализе, ввиду нерепрезентативности. Кроме того, низкий уровень дохода подразумевает, как правило, более низкую сумму кредита, так что этими категориями можно пренебречь. В категориях 'B' и 'C' уже заметны достаточно весомые различия, что позволяет сдлеать следующий вывод - заёмщики с доходом от 200 000 рублей, реже допускают просроченные платежи, чем заёмщики с доходом в диапазоне 50 000 - 100 000 рублей. Больше доход - меньше вероятны "слуйчайные", незапланированные траты. Финансовая подушка безопасности - наше всё!
  491.     Отдельно стоит выделить категорию высокодоходных заемщиков('A'). Несмотря на их небольшое количество, суммы кредитов могут быть очень значительными, поэтому, более корректные выводы можно будет сделать при наличии информации по изначальной сумме кредитного договора. Либо использовать медианное значение при категоризации уровня дохода.
  492.  
  493. <div class="alert alert-success">
  494. <h3> Комментарий ревьюера v2<a class="tocSkip"> </h3>
  495.  
  496. <b>Все отлично!✔️:</b> Да, ты правильно выбрал категории для анализа. Стоит сказать, что более богатым людям кредиты выдают под более выгодный процент, что снижает нагрузку на богатого клиента.
  497. </div>
  498.  
  499. #### 3.4 Как разные цели кредита влияют на его возврат в срок?
  500.  
  501. debtor_purpose = data.groupby('purpose_category')['debt'].agg(['count', 'sum', 'mean'])
  502.  
  503. debtor_purpose['mean'] = debtor_purpose['mean'].apply('{:2%}'.format)
  504.  
  505. debtor_purpose = debtor_purpose.sort_values(by='mean',ascending=False)
  506.  
  507. debtor_purpose = debtor_purpose.rename(columns={'count':'Заемщики','sum':'Должники','mean':'Процент должников'})
  508.  
  509. debtor_purpose
  510.  
  511. # Вывод
  512.  
  513. Заёмщики, приобретающие транспортное средство или получающие образование, очевидно, менее надежны, чем женихи и невесты. Вероятно, на машине и знаниях много не заработать, а подаренных на свадьбу денег хватает, чтобы не допустить просроченного платежа по кредиту. Отдельно стоят самые надежные плательщики - счастливые обладатели ипотеки. Тут всё ясно - плати или вылетишь на улицу.
  514.  
  515. <div class="alert alert-success">
  516. <h3> Комментарий ревьюера v2<a class="tocSkip"> </h3>
  517.  
  518. <b>Все отлично!✔️:</b> С выводами согласен, кредиты на образование, вероятно, берут молодые люди, которые не имеют стабильного заработка, а автомобиль может включать дополнительные расходы, которые не для всех могут быть явными на этапе выбора кредита.
  519. </div>
  520.  
  521. #### 3.5 Приведите возможные причины появления пропусков в исходных данных.
  522.  
  523. Причины пропуска в данных можно  условно разделить на две группы - технологические и вызванные человеческим фактором.
  524.  
  525. Технологические причины:
  526.  
  527. - сбой при записи
  528. - смена формата
  529. - ошибки при считывании
  530.  
  531. Человеческий фактор:
  532.  
  533. - некорректный ввод данных
  534. - сокрытие информации
  535. - фрод
  536.  
  537. <div class="alert alert-success">
  538. <h3> Комментарий ревьюера v2<a class="tocSkip"> </h3>
  539.  
  540. <b>Все отлично!✔️:</b> Да, абсолютно верно, даже и добавить нечего.
  541. </div>
  542.  
  543. #### 3.6 Объясните, почему заполнить пропуски медианным значением — лучшее решение для количественных переменных.
  544.  
  545. Среднее значение некорректно характеризует данные в том случае, когда некоторые количественные значения сильно отличаются от большинства других. Медиана даёт более правдоподобную картину.
  546.  
  547. <div class="alert alert-success">
  548. <h3> Комментарий ревьюера v2<a class="tocSkip"> </h3>
  549.  
  550. <b>Все отлично!✔️:</b> Верно, медиана гораздо более устойчива к экстремальным значениям или выбросам, чем среднее. И более устойчива она потому что делит выборку на две равные части по количеству измерений, а среднее учитывает выраженность каждого измерения.
  551. </div>
  552.  
  553. ### Шаг 4: общий вывод.
  554.  
  555. # Общий вывод по итогам
  556.  
  557.     Проведя анализ предоставленных данных, можно отметить, что в сфере кредитования, как впрочем и везде, мелочей не бывает. Банку при скоринге очень важно обращать внимание на разные аспекты жизни заемщика,т.к. вероятность просроченного платежа зависит не только от дохода клиента.
  558.     Как мы видим из результатов, влияние также оказывает семейное положение заемщика, количество детей и вид кредита. Кроме того, крайне важно следить за качеством получаемых данных и подбирать правильные инструменты для анализа (например, в случае выбора между поиском среднего значения и медианы), т.к. это напрямую влияет на результат исследования, и, соответсвенно, на качество прогноза.  
  559.     Для более точного ответа и корректного прогноза, я бы предложил так же собирать данные о сумме кредита. Это позволит  более глубоко проанализировать данные и получить больше информации. В свою очередь, это сделает процедуру скоринга более "справедливой" и точной, соответственно банк снизит потенциальные риски.
  560.     А если исходить из текущих данных - бездетный вдовец с доходом от 200 000 рублей, вступающий в ипотеку - почти идеальный заёмщик для банка, и это обязательно нужно учитывать при проведении скоринга.
  561.  
  562. <div class="alert alert-danger">
  563.     <h3> Комментарий ревьюера v2<a class="tocSkip"> </h3>
  564.  
  565. <b>На доработку❌:</b> Хорошо, что ты описываешь портрет идеального клиента. Однако этого недостаточно, так как твой потенциальный руководитель, в первую очередь, обратит внимание на общий вывод, поэтому необходимо отразить в нём все пункты проекта. Дополни, пожалуйста, финальный вывод основными идеями промежуточных выводов.
  566.        
  567. </div>
  568.  
  569. <div class="alert alert-block alert-info">
  570.    
  571. <h3> Комментарий студента  <a class="tocSkip"></h3>
  572.    
  573. Комментарии учёл, общий вывод подкорректировал.
  574.    
  575. </div>
  576.  
  577. <div class="alert alert-warning">
  578.     <h3> Комментарий ревьюера v3<a class="tocSkip"> </h3>
  579.  
  580. <b>Некоторые замечания и рекомендации⚠️:</b> Хорошо, что ты рассказал о этапах проделанной работы, однако стоит приводить и данные в числах, какие группы более рискованные, а какие менее. Учитывай, пожалуйста, это в будущих проектах.
  581. </div>
  582.  
  583.  
  584.  
  585.  
Advertisement
Add Comment
Please, Sign In to add comment