Перевод внезапно удачно попал в струю других датасайенсных туториалов на хабре. :)
Этот написан Виком Паручури, основателем Dataquest.io, где как раз и занимаются подобного рода интерактивным обучением data science и подготовкой к реальной работе в этой области. Каких-то эксклюзивных ноу-хау здесь нет, но очень подробно рассказан процесс от сбора данных до первичных выводов о них, что может быть интересно не только желающим составить резюме на data science, но и тем, кто просто хочет попробовать себя в практическом анализе, но не знает, с чего начать.
Data science-компании всё чаще смотрят портфолио, когда принимают решение о приёме на работу. Это, в частности, из-за того, что лучший способ судить о практических навыках — именно портфолио. И хорошая новость в том, что оно полностью в вашем распоряжении: если постараетесь – сможете собрать отличное портфолио, которым будут впечатлены многие компании.
Первый шаг в высококачественному портфолио – это понимание, какие умения в нём надо продемонстрировать.
Основные навыки, которые компании хотят видеть в data scientist-ах, и, соответственно, продемонстрированными в их портфолио, это:
Способность общаться
Способность сотрудничать с другими
Техническая компетенция
Способность делать заключения на основе данных
Мотивация и способность проявить инициативу.
Всякое хорошее портфолио содержит несколько проектов, каждый из которых может демонстрировать 1-2 данных пункта. Это первый пост из цикла, который будет рассматривать получение гармоничного data science-портфолио. Мы рассмотрим, как сделать первый проект для портфолио, и как рассказать хорошую историю через данные. В конце будет проект, который поможет раскрыть вашу способность общаться и способность делать заключения на основе данных.
Прим. перев.
Я точно не буду переводить весь цикл, но планирую коснуться интересного туториала о машинном обучении оттуда же.
История через данные
В принципе, Data science вся состоит из общения. Вы видите в данных какую-то закономерность, потом ищете эффективный способ объяснить эту закономерность другим, потом убеждаете их предпринять те действия, которые вы считаете нужными. Одно из важнейших умений в data science — наглядно рассказать историю через данные. Удачная история может лучше преподнести ваши догадки и помочь другим понять ваши идеи.
История в контексте data science — это изложение всего того, что вы нашли и того, что это значит. Примером может служить открытие того, что прибыль вашей компании снизилась на 20% за последний год. Просто указать на этот факт недостаточно: надо объяснить, почему прибыль упала и что с этим делать.
Основные компоненты историй в данных это:
Понимание и формирование контекста
Исследование под разными ракурсами
Использование подходящих визуализаций
Использование различных источников данных
Связное изложение.
Лучшее средство доходчиво рассказать историю через данные — это Jupyter notebook. Если вы с ним незнакомы — тут хороший туториал. Jupyter notebook позволяет интерактивно исследовать данные и публиковать их на различных сайтах, включая гитхаб. Публикация результатов полезна для сотрудничества — ваш анализ смогут расширить другие люди.
Мы в этом посте будем использовать Jupyter notebook вместе с питоновскими библиотеками типа Pandas и matplotlib.
Выбор темы вашего data science-проекта
Первый шаг к созданию проекта — это определиться с темой. Стоит выбрать что-то, что вам интересно и что есть желание поисследовать. Всегда видно, когда люди сделали проект просто чтобы было, а когда потому, что им действительно интересно было покопаться в данных. На этом шаге имеет смысл потратить время, чтобы точно найти что-то увлекающее.
Хороший способ найти тему — полазить по разным датасетам и посмотреть, что есть интересного. Вот хорошие места для начала:
В реальной data science часто не получается найти полностью подготовленный для ваших изысканий датасет. Возможно, придётся агрегировать различные источники данных или серьёзно их чистить. Если тема вам очень интересна — имеет смысл сделать то же и здесь: лучше покажете себя в итоге.
Мы для поста будем использовать данные о Нью-Йоркских общеобразовательных школах, отсюда.
Прим. перев.
На всякий случай, приведу пример более близких к нам (россиянам) аналогичных датасетов:
Важно сделать весь проект от начала до конца. Для этого полезно ограничить область изучения так, чтобы точно знать, что вы закончите. Проще добавить что-то к уже завершённому проекту, чем пытаться закончить то, что уже попросту надоело доводить до конца.
В нашем случае, мы будем изучать оценки ЕГЭ старшеклассников вместе с различной демографической и прочей информацией о них. ЕГЭ или Единый Государственный экзамен — это тест, который старшеклассники сдают перед поступлением в колледж. Колледжи учитывают оценки, когда принимают решение о зачислении, так что хорошо сдать его — весьма важно. Экзамен состоит из трёх частей, каждая из которых оценивается в 800 баллов. Общий балл в итоге 2400 (хотя иногда это плавало туда-сюда - в датасете всё по 2400). Старшие школы часто оцениваются по среднему баллу ЕГЭ и высокий средний балл обычно является показателем того, насколько хорош школьный округ.
Были определённые жалобы на несправедливость оценок некоторым нацменьшинствам в США, поэтому анализ по Нью-Йорку поможет пролить свет на справедливость ЕГЭ.
Датасет с оценками ЕГЭ — здесь, а датасет с информацией по каждой школе — здесь. Это будет основой нашего проекта, но нам понадобится ещё информация, чтобы сделать полноценный анализ.
Прим. перев.
В оригинале экзамен называется SAT — Scholastic Aptitude Test. Но поскольку он практически по смыслу идентичен нашему ЕГЭ — решил так его и переводить.
Собираем данные
Как только есть хорошая тема — полезно просмотреть другие датасеты, которые могут расширить тему или помочь углубить исследование. Лучше делать это в начале, чтобы было как можно больше данных для исследования по мере создания проекта. Если данных будет мало — есть шанс, что вы сдадитесь слишком рано.
В нашем случае, есть ещё несколько датасетов по этой теме на том же сайте, которые освещают демографическую информацию и результаты экзаменов.
Вот ссылки на все датасеты, что будем использовать:
Демография – демографическая информация по каждой школе.
Школьные опросы – опросы родителей, учителей и учеников в каждой школе.
Карта школьных округов – содержит информацию о форме школьных округов, так что мы сможем нанести их на карту.
Все эти данные связаны между собой, и мы сможем их объединить прежде, чем начнём анализ.
Сбор вводной информации
Прежде, чем погружаться в анализ данных, полезно выяснить общую информацию о предмете. В нашем случае, мы знаем кое-что, что может оказаться полезным:
Нью-Йорк поделен на 5 районов, которые являются практически отдельными областями.
Школы в Нью-Йорке поделены на несколько школьных округов, каждый может содержать десятки школ.
Не все школы в датасете — старшие, так что, возможно, потребуется предварительно почистить данные
Каждая школа в Нью-Йорке имеет уникальный код DBN или районно-окружной номер.
Агрегируя данные по округам, мы сможем использовать их картографическую информацию, чтобы на карте изобразить отличия между ними.
Прим. перев.
То, что я перевёл как "Районы" на самом деле называется в NYC "боро", и столбцы, соответственно, называются Borough.
Понимаем данные
Чтобы действительно понять контекст данных, нужно потратить время и об этих данных почитать. В нашем случае, каждая вышеприведённая ссылка содержит описание данных для каждой колонки. Похоже, у нас есть данные по оценкам ЕГЭ старшеклассников, вместе с другими датасетами, которые содержат демографическую и прочую информацию.
Запустим кое-какой код, чтобы прочесть данные. Используем Jupyter notebook для наших исследований. Нижеприведённый код:
import pandas
import numpy as np
files = ["ap_2010.csv", "class_size.csv", "demographics.csv", "graduation.csv", "hs_directory.csv", "math_test_results.csv", "sat_results.csv"]
data = {}
for f in files:
d = pandas.read_csv("schools/{0}".format(f))
data[f.replace(".csv", "")] = d
Как только мы всё прочитали, можно использовать на датафреймах метод head, чтобы вывести первые 5 строк каждого:
for k,v in data.items():
print("n" + k + "n")
print(v.head())
Уже можно видеть в датасетах определённые особенности: math_test_results
DBN
Grade
Year
Category
Number Tested
Mean Scale Score
Level 1 #
0
01M015
3
2006
All Students
39
667
2
1
01M015
3
2007
All Students
31
672
2
2
01M015
3
2008
All Students
37
668
0
3
01M015
3
2009
All Students
33
668
0
4
01M015
3
2010
All Students
26
677
6
Level 1 %
Level 2 #
Level 2 %
Level 3 #
Level 3 %
Level 4 #
Level 4 %
0
5.1%
11
28.2%
20
51.3%
6
15.4%
1
6.5%
3
9.7%
22
71%
4
12.9%
2
0%
6
16.2%
29
78.4%
2
5.4%
3
0%
4
12.1%
28
84.8%
1
3%
4
23.1%
12
46.2%
6
23.1%
2
7.7%
Level 3+4 #
Level 3+4 %
0
26
66.7%
1
26
83.9%
2
31
83.8%
3
29
87.9%
4
8
30.8%
ap_2010
DBN
SchoolName
AP Test Takers
Total Exams Taken
Number of Exams with scores 3 4 or 5
0
01M448
UNIVERSITY NEIGHBORHOOD H.S.
39
49
10
1
01M450
EAST SIDE COMMUNITY HS
19
21
s
2
01M515
LOWER EASTSIDE PREP
24
26
24
3
01M539
NEW EXPLORATIONS SCI,TECH,MATH
255
377
191
4
02M296
High School of Hospitality Management
s
s
s
sat_results
DBN
SCHOOL NAME
Num of SAT Test Takers
SAT Critical Reading Avg. Score
SAT Math Avg. Score
SAT Writing Avg. Score
0
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES
29
355
404
363
1
01M448
UNIVERSITY NEIGHBORHOOD HIGH SCHOOL
91
383
423
366
2
01M450
EAST SIDE COMMUNITY SCHOOL
70
377
402
370
3
01M458
FORSYTH SATELLITE ACADEMY
7
414
401
359
4
01M509
MARTA VALLE HIGH SCHOOL
44
390
433
384
class_size
CSD
BOROUGH
SCHOOL CODE
SCHOOL NAME
GRADE
PROGRAM TYPE
CORE SUBJECT (MS CORE and 9-12 ONLY)
CORE COURSE (MS CORE and 9-12 ONLY)
0
1
M
M015
P.S. 015 Roberto Clemente
0K
GEN ED
-
-
1
1
M
M015
P.S. 015 Roberto Clemente
0K
CTT
-
-
2
1
M
M015
P.S. 015 Roberto Clemente
01
GEN ED
-
-
3
1
M
M015
P.S. 015 Roberto Clemente
01
CTT
-
-
4
1
M
M015
P.S. 015 Roberto Clemente
02
GEN E
-
-
SERVICE CATEGORY(K-9* ONLY)
NUMBER OF STUDENTS / SEATS FILLED
NUMBER OF SECTIONS
AVERAGE CLASS SIZE
SIZE OF SMALLEST CLASS
0
-
19.0
1.0
19.0
19.0
1
-
21.0
1.0
21.0
21.0
2
-
17.0
1.0
17.0
17.0
3
-
17.0
1.0
17.0
17.0
4
-
15.0
1.0
15.0
15.0
SIZE OF LARGEST CLASS
DATA SOURCE
SCHOOLWIDE PUPIL-TEACHER RATIO
0
19.0
ATS
NaN
1
21.0
ATS
NaN
2
17.0
ATS
NaN
3
17.0
ATS
NaN
4
15.0
ATS
NaN
demographics
DBN
Name
schoolyear
fl_percent
frl_percent
0
01M015
P.S. 015 ROBERTO CLEMENTE
20052006
89.4
NaN
1
01M015
P.S. 015 ROBERTO CLEMENTE
20062007
89.4
NaN
2
01M015
P.S. 015 ROBERTO CLEMENTE
20072008
89.4
NaN
3
01M015
P.S. 015 ROBERTO CLEMENTE
20082009
89.4
NaN
4
01M015
P.S. 015 ROBERTO CLEMENTE
20092010
96.5
total_enrollment
prek
k
grade1
grade2
...
black_num
black_per
0
281
15
36
40
33
...
74
26.3
1
243
15
29
39
38
...
68
28.0
2
261
18
43
39
36
...
77
29.5
3
252
17
37
44
32
...
75
29.8
4
208
16
40
28
32
...
67
32.2
hispanic_num
hispanic_per
white_num
white_per
male_num
male_per
female_num
female_per
0
189
67.3
5
1.8
158.0
56.2
123.0
43.8
1
153
63.0
4
1.6
140.0
57.6
103.0
42.4
2
157
60.2
7
2.7
143.0
54.8
118.0
45.2
3
149
59.1
7
2.8
149.0
59.1
103.0
40.9
4
118
56.7
6
2.9
124.0
59.6
84.0
40.4
graduation
Demographic
DBN
School Name
Cohort
0
Total Cohort
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL
2003
1
Total Cohort
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL
2004
2
Total Cohort
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL
2005
3
Total Cohort
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL
2006
4
Total Cohort
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL
2006 Aug
Total Cohort
Total Grads — n
Total Grads — % of cohort
Total Regents — n
0
5
s
s
s
1
55
37
67.3%
17
2
64
43
67.2%
27
3
78
43
55.1%
36
4
78
44
56.4%
37
Total Regents — % of cohort
Total Regents — % of grads
...
Regents w/o Advanced — n
0
s
s
...
s
1
30.9%
45.9%
...
17
2
42.2%
62.8%
...
27
3
46.2%
83.7%
...
36
4
47.4%
84.1%
...
37
Regents w/o Advanced — % of cohort
Regents w/o Advanced — % of grads
0
s
s
1
30.9%
45.9%
2
42.2%
62.8%
3
46.2%
83.7%
4
47.4%
84.1%
Local — n
Local — % of cohort
Local — % of grad
s Still Enrolled — n
0
s
s
s
s
1
20
36.4%
54.1%
15
2
16
25%
37.200000000000003%
9
3
7
9%
16.3%
16
4
7
9%
15.9%
15
Still Enrolled — % of cohort
Dropped Out — n
Dropped Out — % of cohort
0
s
s
s
1
27.3%
3
5.5%
2
14.1%
9
14.1%
3
20.5%
11
14.1%
4
19.2%
11
14.1%
hs_directory
dbn
school_name
boro
0
17K548
Brooklyn School for Music & Theatre
Brooklyn
1
09X543
High School for Violin and Dance
Bronx
2
09X327
Comprehensive Model School Project M.S. 327
Bronx
3
02M280
Manhattan Early College School for Advertising
Manhattan
4
28Q680
Queens Gateway to Health Sciences Secondary Sc...
Queens
building_code
phone_number
fax_number
grade_span_min
grade_span_max
0
K440
718-230-6250
718-230-6262
9
12
1
X400
718-842-0687
718-589-9849
9
12
2
X240
718-294-8111
718-294-8109
6
12
3
M520
718-935-3477
NaN
9
10
4
Q695
718-969-3155
718-969-3552
6
12
expgrade_span_min
expgrade_span_max
...
priority02
0
NaN
NaN
...
Then to New York City residents
1
NaN
NaN
...
Then to New York City residents who attend an ...
2
NaN
NaN
...
Then to Bronx students or residents who attend...
3
9
14.0
...
Then to New York City residents who attend an ...
4
NaN
NaN
...
Then to Districts 28 and 29 students or residents
priority03
priority04
priority05
0
NaN
NaN
NaN
1
Then to Bronx students or residents
Then to New York City residents
NaN
2
Then to New York City residents who attend an ...
Then to Bronx students or residents
Then to New York City residents
3
Then to Manhattan students or residents
Then to New York City residents
NaN
4
Then to Queens students or residents
Then to New York City residents
NaN
priority06
priority07
priority08
priority09
priority10
Location 1
0
NaN
NaN
NaN
NaN
NaN
883 Classon AvenuenBrooklyn, NY 11225n(40.67...
1
NaN
NaN
NaN
NaN
NaN
1110 Boston RoadnBronx, NY 10456n(40.8276026...
2
NaN
NaN
NaN
NaN
NaN
1501 Jerome AvenuenBronx, NY 10452n(40.84241...
3
NaN
NaN
NaN
NaN
NaN
411 Pearl StreetnNew York, NY 10038n(40.7106...
4
NaN
NaN
NaN
NaN
NaN
160-20 Goethals AvenuenJamaica, NY 11432n(40...
Большинство содержит столбец DBN
Некоторые поля выглядят интересными для картографирования, в частности Location 1, который содержит координаты в строке.
В некоторых датасетах есть по несколько строк на каждую школу (повторяющиеся значения DBN), что намекает на необходимость предварительной обработки.
Приведение данных к общему знаменателю
Чтобы с данными работать было легче, нам надо объединить все датасеты в один — это позволит нам быстро сравнивать колонки в датасетах. Для этого, прежде всего, надо найти общую колонку для объединения. Глядя на то, что нам ранее вывелось, можно предположить, что такой колонкой может быть DBN, поскольку она повторяется в нескольких датасетах.
Если мы загуглим "DBN New York City Schools", то придём сюда, где объясняется, что DBN — это уникальный код для каждой школы. При исследовании датасетов, особенно правительственных, приходится частенько проделать детективную работу, чтобы понять, что значит каждый столбец, даже каждый датасет иногда.
Теперь проблема в том, что два датасета, class_size и hs_directory — не содержат DBN. В hs_directory он называется dbn, поэтому просто переименуем или скопируем его в DBN. Для class_size нужен будет другой подход.
Столбец DBN выглядит так:
Если посмотрим на class_size - вот то, что мы увидим в первых 5 строках:
In [4]:
data["class_size"].head()
Out[4]:
CSD
BOROUGH
SCHOOL CODE
SCHOOL NAME
GRADE
PROGRAM TYPE
CORE SUBJECT (MS CORE and 9-12 ONLY)
/
0
1
M
M015
P.S. 015 Roberto Clemente
0K
GEN ED
-
1
1
M
M015
P.S. 015 Roberto Clemente
0K
CTT
-
2
1
M
M015
P.S. 015 Roberto Clemente
01
GEN ED
-
3
1
M
M015
P.S. 015 Roberto Clemente
01
CTT
-
4
1
M
M015
P.S. 015 Roberto Clemente
02
GEN ED
-
CORE COURSE (MS CORE and 9-12 ONLY)
SERVICE CATEGORY(K-9* ONLY)
NUMBER OF STUDENTS / SEATS FILLED
/
0
-
-
19.0
1
-
-
21.0
2
-
-
17.0
3
-
-
17.0
4
-
-
15.0
NUMBER OF SECTIONS
AVERAGE CLASS SIZE
SIZE OF SMALLEST CLASS
SIZE OF LARGEST CLASS
DATA SOURCE
SCHOOLWIDE PUPIL-TEACHER RATIO
0
1.0
19.0
19.0
19.0
ATS
NaN
1
1.0
21.0
21.0
21.0
ATS
NaN
2
1.0
17.0
17.0
17.0
ATS
NaN
3
1.0
17.0
17.0
17.0
ATS
NaN
4
1.0
15.0
15.0
15.0
ATS
NaN
Как можно заметить, DBN — это просто комбинация CSD,BOROUGH и SCHOOL_ CODE. Для незнакомых с Нью-Йорком: он состоит из 5 районов. Каждый район — это организационная единица, приблизительно равная по размеру достаточно большому городу США. DBN расшифровывается как районно-окружной номер. Похоже, что CSD — это округ, BOROUGH — район и в сочетании со SCHOOL_CODE получается DBN.
Теперь, когда мы знаем, как составить DBN, мы можем добавить его в class_size и hs_directory.
Один из самых потенциально интересных датасетов — это датасет опросов учеников, родителей и учителей по поводу качества школ. Эти опросы включают информацию о субъективном восприятии безопасности каждой школы, учебных стандартах и прочем. Перед тем, как объединять наши датасеты, давайте добавим данные по опросам. В реальных data science-проектах вы часто будете натыкаться на интересные данные по ходу анализа и, возможно, захотите так же их подключить. Гибкий инструмент, типа Jupyter notebook, позволяет быстро добавить дополнительный код и переделать анализ.
В нашем случае, добавим дополнительные данные по опросам в наш словарь data, после чего объединим все датасеты. Данные по опросам состоят из двух файлов, один на все школы, и один на школьный округ 75. Чтобы их объединить, потребуется написать немного кода. В нём мы сделаем что:
Прочитаем опросы по всем школам, используя кодировку windows-1252
Прочитаем опросы для округа 75 с использованием windows-1252
Добавим флаг, который будет обозначать, для какого округа каждый датасет.
Объединим все датасеты в один с помощью метода concat на датафреймах.
Как только мы объединим все опросы, появится дополнительная трудность. Мы хотим минимизировать количество столбцов в нашем объединённом датасете, чтобы можно было легко сравнивать колонки и выявлять зависимости. К несчастью, данные по опросам содержат много ненужных нам колонок:
In [16]:
survey.head()
Out[16]:
N_p
N_s
N_t
aca_p_11
aca_s_11
aca_t_11
aca_tot_11
/
0
90.0
NaN
22.0
7.8
NaN
7.9
7.9
1
161.0
NaN
34.0
7.8
NaN
9.1
8.4
2
367.0
NaN
42.0
8.6
NaN
7.5
8.0
3
151.0
145.0
29.0
8.5
7.4
7.8
7.9
4
90.0
NaN
23.0
7.9
NaN
8.1
8.0
bn
com_p_11
com_s_11
...
t_q8c_1
t_q8c_2
t_q8c_3
t_q8c_4
/
0
M015
7.6
NaN
...
29.0
67.0
5.0
0.0
1
M019
7.6
NaN
...
74.0
21.0
6.0
0.0
2
M020
8.3
NaN
...
33.0
35.0
20.0
13.0
3
M034
8.2
5.9
...
21.0
45.0
28.0
7.0
4
M063
7.9
NaN
...
59.0
36.0
5.0
0.0
t_q9
t_q9_1
t_q9_2
t_q9_3
t_q9_4
t_q9_5
0
NaN
5.0
14.0
52.0
24.0
5.0
1
NaN
3.0
6.0
3.0
78.0
9.0
2
NaN
3.0
5.0
16.0
70.0
5.0
3
NaN
0.0
18.0
32.0
39.0
11.0
4
NaN
10.0
5.0
10.0
60.0
15.0
Мы справимся с этим, заглянув в файл со словарём данных, который мы скачали вместе с данными по опросам. Он расскажет нам про важные поля:
А потом мы удалим все не относящиеся к нам столбцы в survey:
Понимание того, что именно содержит каждый датасет и какие столбцы из него важны, может сэкономить кучу времени и усилий в дальнейшем.
Уплотняем датасеты
Если мы взглянем на некоторые датасеты, включая class_size, мы сразу увидим проблему:
In [18]: data["class_size"].head()
Out[18]:
CSD
BOROUGH
SCHOOL CODE
SCHOOL NAME
GRADE
PROGRAM TYPE
CORE SUBJECT (MS CORE and 9-12 ONLY)
/
0
1
M
M015
P.S. 015 Roberto Clemente
0K
GEN ED
-
1
1
M
M015
P.S. 015 Roberto Clemente
0K
CTT
-
2
1
M
M015
P.S. 015 Roberto Clemente
01
GEN ED
-
3
1
M
M015
P.S. 015 Roberto Clemente
01
CTT
-
4
1
M
M015
P.S. 015 Roberto Clemente
02
GEN ED
-
CORE COURSE (MS CORE and 9-12 ONLY)
SERVICE CATEGORY(K-9* ONLY)
NUMBER OF STUDENTS / SEATS FILLED
NUMBER OF SECTIONS
AVERAGE CLASS SIZE
/
0
-
-
19.0
1.0
19.0
1
-
-
21.0
1.0
21.0
2
-
-
17.0
1.0
17.0
3
-
-
17.0
1.0
17.0
4
-
-
15.0
1.0
15.0
SIZE OF SMALLEST CLASS
SIZE OF LARGEST CLASS
DATA SOURCE
SCHOOLWIDE PUPIL-TEACHER RATIO
DBN
0
19.0
19.0
ATS
NaN
01M015
1
21.0
21.0
ATS
NaN
01M015
2
17.0
17.0
ATS
NaN
01M015
3
17.0
17.0
ATS
NaN
01M015
4
15.0
15.0
ATS
NaN
01M015
Для каждой школы есть несколько строк (что можно понять по повторяющимся полям DBN и SCHOOL NAME). Хотя, если мы взглянем на sat_results - в нём только по одной строке на школу:
In [21]:
data["sat_results"].head()
Out[21]:
DBN
SCHOOL NAME
Num of SAT Test Takers
SAT Critical Reading Avg. Score
SAT Math Avg. Score
SAT Writing Avg. Score
0
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES
29
355
404
363
1
01M448
UNIVERSITY NEIGHBORHOOD HIGH SCHOOL
91
383
423
366
2
01M450
EAST SIDE COMMUNITY SCHOOL
70
377
402
370
3
01M458
FORSYTH SATELLITE ACADEMY
7
414
401
359
4
01M509
MARTA VALLE HIGH SCHOOL
44
390
433
384
Чтобы объединить эти датасеты, нужен способ уплотнить датасеты типа class_size так, чтобы в них было по одной строке на каждую старшую школу. Если не получится — то не получится и сравнить оценки ЕГЭ с размерами класса. Мы сможем этого достичь, получше разобравшись в данных, а потом сделав некоторые агрегации.
По датасету class_size - похоже, что GRADE и PROGRAM TYPE содержат разные оценки по каждой школе. Ограничив каждое поле единственным значением, мы сможем отбросить все строчки-дубликаты. В коде ниже мы:
Выберем только те значения из class_size, где поле GRADE - 09-12.
Выберем только те значения из class_size, где поле PROGRAM TYPE - GEN ED.
Сгруппируем class_size по DBN, и возьмём среднее по каждой колонке. По сути, мы найдем средний class_size по каждой школе.
Сбросим индекс, чтобы DBN снова добавился как колонка.
Дальше нам надо ужать датасет demographics. Данные собраны за несколько лет по одним и тем же школам. Мы выберем только те строки, где поле schoolyear свежее всего.
Очистка и исследование данных критичны перед работой над сутью проекта. Хороший, годныйцелостный датасет поможет быстрее сделать анализ.
Вычисление агрегированных переменных
Вычисление переменных может ускорить наш анализ возможностью делать сравнивание быстрее и в принципе давая возможность делать некоторые, невозможные без них, сравнения. Первое, что мы можем сделать — посчитать общий балл ЕГЭ из отдельных колонок SAT Math Avg. Score, SAT Critical Reading Avg. Score, и SAT Writing Avg. Score. В коде ниже мы:
Преобразуем каждый балл ЕГЭ от строки к числу
Сложим все столбцы и получим столбец sat_score, суммарный балл ЕГЭ.
In [72]:
cols = ['SAT Math Avg. Score', 'SAT Critical Reading Avg. Score', 'SAT Writing Avg. Score']
for c in cols:
data["sat_results"][c] = data["sat_results"][c].convert_objects(convert_numeric=True)
data['sat_results']['sat_score'] = data['sat_results'][cols[0]] + data['sat_results'][cols[1]]
Далее нам надо распарсить координаты каждой школы, чтобы делать карты. Они позволят нам отметить положение каждой школы. В коде мы:
Распарсим в столбцы широты и долготы столбец Location 1
Преобразуем lat и lon к числам.
Выведем наши датасеты, посмотрим, что получилось:
In [74]:
for k,v in data.items():
print(k)
print(v.head())
math_test_results
DBN
Grade
Year
Category
Number Tested
Mean Scale Score
111
01M034
8
2011
All Students
48
646
280
01M140
8
2011
All Students
61
665
346
01M184
8
2011
All Students
49
727
388
01M188
8
2011
All Students
49
658
411
01M292
8
2011
All Students
49
650
Level 1 #
Level 1 %
Level 2 #
Level 2 %
Level 3 #
Level 3 %
Level 4 #
111
15
31.3%
22
45.8%
11
22.9%
0
280
1
1.6%
43
70.5%
17
27.9%
0
346
0
0%
0
0%
5
10.2%
44
388
10
20.4%
26
53.1%
10
20.4%
3
411
15
30.6%
25
51%
7
14.3%
2
Level 4 %
Level 3+4 #
Level 3+4 %
111
0%
11
22.9%
280
0%
17
27.9%
346
89.8%
49
100%
388
6.1%
13
26.5%
411
4.1%
9
18.4%
survey
DBN
rr_s
rr_t
rr_p
N_s
N_t
N_p
saf_p_11
com_p_11
eng_p_11
0
01M015
NaN
88
60
NaN
22.0
90.0
8.5
7.6
7.5
1
01M019
NaN
100
60
NaN
34.0
161.0
8.4
7.6
7.6
2
01M020
NaN
88
73
NaN
42.0
367.0
8.9
8.3
8.3
3
01M034
89.0
73
50
145.0
29.0
151.0
8.8
8.2
8.0
4
01M063
NaN
100
60
NaN
23.0
90.0
8.7
7.9
8.1
...
eng_t_10
aca_t_11
saf_s_11
com_s_11
eng_s_11
aca_s_11
0
...
NaN
7.9
NaN
NaN
NaN
NaN
1
...
NaN
9.1
NaN
NaN
NaN
NaN
2
...
NaN
7.5
NaN
NaN
NaN
NaN
3
...
NaN
7.8
6.2
5.9
6.5
7.4
4
...
NaN
8.1
NaN
NaN
NaN
NaN
saf_tot_11
com_tot_11
eng_tot_11
aca_tot_11
0
8.0
7.7
7.5
7.9
1
8.5
8.1
8.2
8.4
2
8.2
7.3
7.5
8.0
3
7.3
6.7
7.1
7.9
4
8.5
7.6
7.9
8.0
ap_2010
DBN
SchoolName
AP Test Takers
Total Exams Taken
Number of Exams with scores 3 4 or 5
0
01M448
UNIVERSITY NEIGHBORHOOD H.S.
39
49
10
1
01M450
EAST SIDE COMMUNITY HS
19
21
s
2
01M515
LOWER EASTSIDE PREP
24
26
24
3
01M539
NEW EXPLORATIONS SCI,TECH,MATH
255
377
191
4
02M296
High School of Hospitality Management
s
s
s
sat_results
DBN
SCHOOL NAME
Num of SAT Test Takers
SAT Critical Reading Avg. Score
0
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES
29
355.0
1
01M448
UNIVERSITY NEIGHBORHOOD HIGH SCHOOL
91
383.0
2
01M450
EAST SIDE COMMUNITY SCHOOL
70
377.0
3
01M458
FORSYTH SATELLITE ACADEMY
7
414.0
4
01M509
MARTA VALLE HIGH SCHOOL
44
390.0
SAT Math Avg. Score
SAT Writing Avg. Score
sat_score
0
404.0
363.0
1122.0
1
423.0
366.0
1172.0
2
402.0
370.0
1149.0
3
401.0
359.0
1174.0
4
433.0
384.0
1207.0
class_size
DBN
CSD
NUMBER OF STUDENTS / SEATS FILLED
NUMBER OF SECTIONS
0
01M292
1
88.0000
4.000000
1
01M332
1
46.0000
2.000000
2
01M378
1
33.0000
1.000000
3
01M448
1
105.6875
4.750000
4
01M450
1
57.6000
2.733333
AVERAGE CLASS SIZE
SIZE OF SMALLEST CLASS
SIZE OF LARGEST CLASS
SCHOOLWIDE PUPIL-TEACHER RATIO
0
22.564286
18.50
26.571429
NaN
1
22.000000
21.00
23.500000
NaN
2
33.000000
33.00
33.000000
NaN
3
22.231250
18.25
27.062500
NaN
4
21.200000
19.40
22.866667
NaN
demographics
DBN
Name
schoolyear
6
01M015
P.S. 015 ROBERTO CLEMENTE
20112012
13
01M019
P.S. 019 ASHER LEVY
20112012
20
01M020
PS 020 ANNA SILVER
20112012
27
01M034
PS 034 FRANKLIN D ROOSEVELT
20112012
35
01M063
PS 063 WILLIAM MCKINLEY
20112012
fl_percent
frl_percent
total_enrollment
prek
k
grade1
grade2
6
NaN
89.4
189
13
31
35
28
13
NaN
61.5
328
32
46
52
54
20
NaN
92.5
626
52
102
121
87
27
NaN
99.7
401
14
34
38
36
35
NaN
78.9
176
18
20
30
21
...
black_num
black_per
hispanic_num
hispanic_per
white_num
6
...
63
33.3
109
57.7
4
13
...
81
24.7
158
48.2
28
20
...
55
8.8
357
57.0
16
27
...
90
22.4
275
68.6
8
35
...
41
23.3
110
62.5
15
white_per
male_num
male_per
female_num
female_per
6
2.1
97.0
51.3
92.0
48.7
13
8.5
147.0
44.8
181.0
55.2
20
2.6
330.0
52.7
296.0
47.3
27
2.0
204.0
50.9
197.0
49.1
35
8.5
97.0
55.1
79.0
44.9
graduation
Demographic
DBN
School Name
Cohort
3
Total Cohort
01M292
HENRY STREET SCHOOL FOR INTERNATIONAL
2006
10
Total Cohort
01M448
UNIVERSITY NEIGHBORHOOD HIGH SCHOOL
2006
17
Total Cohort
01M450
EAST SIDE COMMUNITY SCHOOL
2006
24
Total Cohort
01M509
MARTA VALLE HIGH SCHOOL
2006
31
Total Cohort
01M515
LOWER EAST SIDE PREPARATORY HIGH SCHO
2006
Total Cohort
Total Grads — n
Total Grads — % of cohort
Total Regents — n
3
78
43
55.1%
36
10
124
53
42.7%
42
17
90
70
77.8%
67
24
84
47
56%
40
31
193
105
54.4%
91
Total Regents — % of cohort
Total Regents — % of grads
...
Regents w/o Advanced — n
3
46.2%
83.7%
...
36
10
33.9%
79.2%
...
34
17
74.400000000000006%
95.7%
...
67
24
47.6%
85.1%
...
23
31
47.2%
86.7%
...
22
Regents w/o Advanced — % of cohort
Regents w/o Advanced — % of grads
3
46.2%
83.7%
10
27.4%
64.2%
17
74.400000000000006%
95.7%
24
27.4%
48.9%
31
11.4%
21%
Local — n
Local — % of cohort
Local — % of grads
Still Enrolled — n
3
7
9%
16.3%
16
10
11
8.9%
20.8%
46
17
3
3.3%
4.3%
15
24
7
8.300000000000001%
14.9%
25
31
14
7.3%
13.3%
53
Still Enrolled — % of cohort
Dropped Out — n
Dropped Out — % of cohort
3
20.5%
11
14.1%
10
37.1%
20
16.100000000000001%
17
16.7%
5
5.6%
24
29.8%
5
6%
31
27.5%
35
18.100000000000001%
hs_directory
dbn
school_name
boro
0
17K548
Brooklyn School for Music & Theatre
Brooklyn
1
09X543
High School for Violin and Dance
Bronx
2
09X327
Comprehensive Model School Project M.S. 327
Bronx
3
02M280
Manhattan Early College School for Advertising
Manhattan
4
28Q680
Queens Gateway to Health Sciences Secondary Sc...
Queens
building_code
phone_number
fax_number
grade_span_min
grade_span_max
0
K440
718-230-6250
718-230-6262
9
12
1
X400
718-842-0687
718-589-9849
9
12
2
X240
718-294-8111
718-294-8109
6
12
3
M520
718-935-3477
NaN
9
10
4
Q695
718-969-3155
718-969-3552
6
12
expgrade_span_min
expgrade_span_max
...
priority05
priority06
priority07
priority08
0
NaN
NaN
...
NaN
NaN
NaN
NaN
1
NaN
NaN
...
NaN
NaN
NaN
NaN
2
NaN
NaN
...
Then to New York City residents
NaN
NaN
NaN
3
9
14.0
...
NaN
NaN
NaN
NaN
4
NaN
NaN
...
NaN
NaN
NaN
NaN
priority09
priority10
Location 1
0
NaN
NaN
883 Classon AvenuenBrooklyn, NY 11225n(40.67...
1
NaN
NaN
1110 Boston RoadnBronx, NY 10456n(40.8276026...
2
NaN
NaN
1501 Jerome AvenuenBronx, NY 10452n(40.84241...
3
NaN
NaN
411 Pearl StreetnNew York, NY 10038n(40.7106...
4
NaN
NaN
160-20 Goethals AvenuenJamaica, NY 11432n(40...
DBN
lat
lon
0
17K548
40.670299
-73.961648
1
09X543
40.827603
-73.904475
2
09X327
40.842414
-73.916162
3
02M280
40.710679
-74.000807
4
28Q680
40.718810
-73.806500
Объединяем датасеты
После всей подготовки наконец, мы можем объединить все датасеты по столбцу DBN. В итоге у нас получится датасет с сотнями столбцов, из всех исходных. При объединении важно отметить, что в некоторых датасетах нет тех школ, что есть в датасете sat_results. Чтобы это обойти, нам надо объединять датасеты через outer join, тогда мы не потеряем данные. В реальном анализе отсутствие данных — обычное дело. Продемонстрировать возможность исследовать и справляться с таким отсутствием — важная часть портфолио.
Про разные типы джоинов можно почитать здесь.
В коде ниже мы:
Пройдёмся по всем элементам словаря data
Выведем количество неуникальных DBN в каждом
Решим, как будем джоинить — внутренне или внешне.
Объединим элемент с датафреймом full через столбец DBN.
In [75]:
flat_data_names = [k for k,v in data.items()]
flat_data = [data[k] for k in flat_data_names]
full = flat_data[0]
for i, f in enumerate(flat_data[1:]):
name = flat_data_names[i+1]
print(name)
print(len(f["DBN"]) - len(f["DBN"].unique()))
join_type = "inner"
if name in ["sat_results", "ap_2010", "graduation"]:
join_type = "outer"
if name not in ["math_test_results"]:
full = full.merge(f, on="DBN", how=join_type)
full.shape
survey
0
ap_2010
1
sat_results
0
class_size
0
demographics
0
graduation
0
hs_directory
0
Out[75]:
(374, 174)
Добавляем значений
Теперь, когда у нас есть наш полный датафрейм full, у нас есть практически вся информация для нашего анализа. Хотя ещё есть недостающие части. Мы можем захотеть скорреллировать оценки теста по углубленной программе с оценками ЕГЭ, но сначала надо будет преобразовывать эти столбцы к числам, а потом заполнить все пропущенные значения:
In [76]:
cols = ['AP Test Takers ', 'Total Exams Taken', 'Number of Exams with scores 3 4 or 5']
for col in cols:
full[col] = full[col].convert_objects(convert_numeric=True)
full[cols] = full[cols].fillna(value=0)
Далее, надо посчитать столбец school_dist, который обозначает школьный округ. Он позволит нам сравнить школьные округа и рисовать окружную статистику с использованием карт округов, которые мы скачали:
In [77]:
full["school_dist"] = full["DBN"].apply(lambda x: x[:2])
Наконец, нам надо заполнить все пропущенные значения в full средним значением из колонки, чтобы посчитать корреляции
In [79]:
full = full.fillna(full.mean())
Считаем коррелляции
Хороший способ поисследовать датасет и посмотреть, как столбцы связаны с тем, чем нужно — это посчитать корреляции. Это покажет, какие столбцы связаны с интересующим столбцом. Это можно сделать методом corr в датафреймах Pandas. Чем ближе корреляция к 0 — тем слабее связь. Чем ближе к 1 — тем сильнее прямая связь. Чем ближе к -1 — тем сильнее обратная связь:
In [80]:
full.corr()['sat_score']
Out[80]:
Year NaN
Number Tested 8.127817e-02
rr_s 8.484298e-02
rr_t -6.604290e-02
rr_p 3.432778e-02
N_s 1.399443e-01
N_t 9.654314e-03
N_p 1.397405e-01
saf_p_11 1.050653e-01
com_p_11 2.107343e-02
eng_p_11 5.094925e-02
aca_p_11 5.822715e-02
saf_t_11 1.206710e-01
com_t_11 3.875666e-02
eng_t_10 NaN
aca_t_11 5.250357e-02
saf_s_11 1.054050e-01
com_s_11 4.576521e-02
eng_s_11 6.303699e-02
aca_s_11 8.015700e-02
saf_tot_11 1.266955e-01
com_tot_11 4.340710e-02
eng_tot_11 5.028588e-02
aca_tot_11 7.229584e-02
AP Test Takers 5.687940e-01
Total Exams Taken 5.585421e-01
Number of Exams with scores 3 4 or 5 5.619043e-01
SAT Critical Reading Avg. Score 9.868201e-01
SAT Math Avg. Score 9.726430e-01
SAT Writing Avg. Score 9.877708e-01
...
SIZE OF SMALLEST CLASS 2.440690e-01
SIZE OF LARGEST CLASS 3.052551e-01
SCHOOLWIDE PUPIL-TEACHER RATIO NaN
schoolyear NaN
frl_percent -7.018217e-01
total_enrollment 3.668201e-01
ell_num -1.535745e-01
ell_percent -3.981643e-01
sped_num 3.486852e-02
sped_percent -4.413665e-01
asian_num 4.748801e-01
asian_per 5.686267e-01
black_num 2.788331e-02
black_per -2.827907e-01
hispanic_num 2.568811e-02
hispanic_per -3.926373e-01
white_num 4.490835e-01
white_per 6.100860e-01
male_num 3.245320e-01
male_per -1.101484e-01
female_num 3.876979e-01
female_per 1.101928e-01
Total Cohort 3.244785e-01
grade_span_max -2.495359e-17
expgrade_span_max NaN
zip -6.312962e-02
total_students 4.066081e-01
number_programs 1.166234e-01
lat -1.198662e-01
lon -1.315241e-01
Name: sat_score, dtype: float64
Эти данные дают нам ряд подсказок, которые надо будет проработать:
Общая численность в классах (total_enrollment) сильно корреллирует с оценками ЕГЭ (sat_score), чтоб удивительно, потому что, на первый взгляд, маленькие школы, которые лучше работают с отдельными студентами, должны иметь более высокие оценки.
Процент женщин в школе (female_per) позитивно коррелирует с оценками ЕГЭ, в то время как процент мужчин (male_per) — негативно.
Ни один результат опроса не коррелирует сильно с оценками ЕГЭ.
Есть существенное расовое неравенство в оценках ЕГЭ (white_per, asian_per, black_per, hispanic_per).
ell_percent сильно коррелирует в обратную сторону с оценками ЕГЭ.
Каждый пункт — потенциальное место для исследования и истории на основе данных.
Прим. перев.
На всякий случай напомню, что корреляция (и ковариация) показывают только меру линейной зависимости. Если связь есть, но не линейная а, скажем, квадратичная — корреляция ничего толкового не покажет.
Ну и, конечно же, корреляционная связь ни в коем роде не указывает на причину и следствие. Просто, что две величины склонны изменяться пропорционально. Ниже как раз пример с поиском действительной закономерности и разобран.
Определяем контекст
Прежде, чем погружаться в исследование данных, надо бы определить контекст, как для нас самих, так и для тех, кто будет читать потом наш анализ. Хороший способ — исследовательские графики или карты. В нашем случае, мы нарисуем на карте месторасположение наших школ, что поможет читающим понять исследуемую нами проблему.
В коде ниже мы:
Подготовим карту Нью-Йорка
Добавим маркер на карту для каждой школы в городе
Отрисуем карту
In [82]:
import folium
from folium import plugins
schools_map = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
marker_cluster = folium.MarkerCluster().add_to(schools_map)
for name, row in full.iterrows():
folium.Marker([row["lat"], row["lon"]], popup="{0}: {1}".format(row["DBN"], row["school_name"])).add_to(marker_cluster)
schools_map.create_map('schools.html')
schools_map
Out[82]:
Карта в целом помогает, но сложно понять, где же больше всего в Нью-Йорке школ. Сделаем вместо этого тепловую карту:
In [84]:
schools_heatmap = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
schools_heatmap.add_children(plugins.HeatMap([[row["lat"], row["lon"]] for name, row in full.iterrows()]))
schools_heatmap.save("heatmap.html")
schools_heatmap
Out[84]:
Карты округов
Тепловые карты хороши для отображения градиентов, но хочется что-то более структурированное, чтобы отразить разницу в оценках ЕГЭ по городу. Школьные округа подходят для отображения этой информации, т.к. у каждого округа своя администрация. В Нью-Йорке несколько дюжин школьных округов, и каждый занимает небольшую площадь.
Мы можем посчитать оценки за ЕГЭ по округу и нанести их на карту. В коде ниже мы:
Сгруппируем full по школьному округу
Посчитаем среднее в каждой колонке по каждому округу
Преобразуем поле school_dist, удалив нули в начале, чтобы оно соответствовало координатам наших округов
Теперь мы можем нарисовать средний балл ЕГЭ по каждому школьному округу. Для этого прочитаем данные в формате GeoJSON, чтобы определить форму каждого округа, потом сопоставим каждую форму с оценкой с помощью столбца school_dist, и, наконец, нарисуем график.
У нас теперь есть контекст на графике со школами, и оценки ЕГЭ по округам; люди, просматривающие наш анализ лучше поймут контекст датасета. Установив декорации, можем теперь приступить к исследованию тех аспектов, что мы уже установили во время поиска корреляций. Первый аспект — исследовать связь между числом студентов, посещающих школу, и оценками ЕГЭ.
Мы можем исследовать это через диаграмму рассеяния, которая сравнит наполняемость с оценками по всем школам:
In [87]:
%matplotlib inline
full.plot.scatter(x='total_enrollment', y='sat_score')
Out[87]:
<matplotlib.axes._subplots.AxesSubplot at 0x10fe79978>
Видим, что есть кластер слева внизу с низкой наполняемостью и оценками. За исключением него, есть слабая позитивная корреляция между оценками ЕГЭ и общей наполняемостью. График наших корреляций может выявить неожиданные закономерности.
Мы можем исследовать этот момент глубже, узнав названия школ с низкой наполняемостью и оценками:
In [88]:
full[(full["total_enrollment"] < 1000) & (full["sat_score"] < 1000)]["School Name"]
Out[88]:
34 INTERNATIONAL SCHOOL FOR LIBERAL ARTS
143 NaN
148 KINGSBRIDGE INTERNATIONAL HIGH SCHOOL
203 MULTICULTURAL HIGH SCHOOL
294 INTERNATIONAL COMMUNITY HIGH SCHOOL
304 BRONX INTERNATIONAL HIGH SCHOOL
314 NaN
317 HIGH SCHOOL OF WORLD CULTURES
320 BROOKLYN INTERNATIONAL HIGH SCHOOL
329 INTERNATIONAL HIGH SCHOOL AT PROSPECT
331 IT TAKES A VILLAGE ACADEMY
351 PAN AMERICAN INTERNATIONAL HIGH SCHOO
Name: School Name, dtype: object
Поиск в Гугле показывает, что большая часть этих школ для студентов, изучающих английский, и, как итог, с низкой наполняемостью. Это исследование показало, что не наполняемость в целом коррелирует с оценками ЕГЭ — коррелирует то, изучают ли ученики в школе английский как второй язык, или нет.
Исследование изучающих английский и оценок ЕГЭ.
Теперь мы знаем, что процент изучающих английский в школе связан с более низкими оценками ЕГЭ, и можем исследовать эту связь. Столбец ell_percent - это процент изучающих английский в каждой школе. Можем построить диаграмму рассеяния по этой связи:
In [89]:
full.plot.scatter(x='ell_percent', y='sat_score')
Out[89]:
<matplotlib.axes._subplots.AxesSubplot at 0x10fe824e0>
Похоже, есть группа школ с высоким ell_percentage и с низким средним баллом ЕГЭ. Можем это исследовать на уровне округов, определяя процент изучающих английский в каждом округе и смотря, как он связан с оценкой по округу:
In [90]:
show_district_map("ell_percent")
Out[90]:
Как мы видим по двум картам округов, округа с более низким процентом англоизучающих имеют тенденцию к более высоким оценкам ЕГЭ, и наоборот.
Коррелируем оценки по опросам и оценки ЕГЭ
Логично было бы предположить, что результаты опросов учеников, родителей и учителей будут сильно коррелировать с оценками ЕГЭ. Разумно, что школы с более высокими учебными ожиданиями имеют тенденцию к более высоким баллам ЕГЭ. Для проверки этой теории построим график оценок ЕГЭ и различных показателей из опросов:
In [91]:
full.corr()["sat_score"][["rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_tot_11", "com_tot_11", "aca_tot_11", "eng_tot_11"]].plot.bar()
Out[91]:
<matplotlib.axes._subplots.AxesSubplot at 0x114652400>
На удивление, больше всего коррелируют N_p и N_s, число участвовавших в опросе родителей и учеников соответственно. Оба сильно коррелируют с общей наполняемостью, так что скорее всего они испытывают влияние и ell_learners. Ещё одна сильно коррелирующая метрика — saf_t_11. Это то, как оценивают безопасность школы ученики, родители и учителя. Логично, что, чем безопаснее школа — тем более комфортно ученикам там учиться. Хотя, больше ни один фактор, типа вовлечённости, общения и академических ожиданий, не коррелирует с оценками ЕГЭ. Это может объясняться тем, что в Нью-Йорке задают неправильные вопросы в опросах, или что предполагают влияние на эти оценки не тех факторов (если их цель — улучшить оценки ЕГЭ, то такого быть не должно).
Изучаем расы и оценки ЕГЭ
Ещё один аспект для исследования включает в себя расы и оценки ЕГЭ. Там была большая корреляция, и её график поможет нам понять, что происходит:
In [92]:
full.corr()["sat_score"][["white_per", "asian_per", "black_per", "hispanic_per"]].plot.bar()
Out[92]:
<matplotlib.axes._subplots.AxesSubplot at 0x108166ba8>
Похоже, высокий процент белых и азиатских учеников коррелирует с более высокими оценками ЕГЭ, но более высокий процент черных и испанцев коррелирует с более низкими оценками. Для испанских студентов это может быть следствием факта, что там много недавних иммигрантов, изучающих английский. Нанесём на карту процент испаноязычных по округу, чтобы увидеть корреляцию глазами:
In [93]:
show_district_map("hispanic_per")
Out[93]:
Похоже, какая-то корреляция с процентом англоизучающих есть, но надо копнуть глубже в этом и других направлениях расовых различий и оценок ЕГЭ.
Половые различия в оценках ЕГЭ
Последний аспект для исследования — связь между полом и оценками. Мы уже заметили, что более высокий процент женщин в школе имеет тенденцию к корреляции с более высокими баллами ЕГЭ. Мы можем этого отразить на столбчатой диаграмме:
In [94]:
full.corr()["sat_score"][["male_per", "female_per"]].plot.bar()
Out[94]:
<matplotlib.axes._subplots.AxesSubplot at 0x10774d0f0>
Чтобы лучше разобраться в корреляции, сделаем диаграмму рассеяния между female_per и sat_score:
In [95]:
full.plot.scatter(x='female_per', y='sat_score')
Out[95]:
<matplotlib.axes._subplots.AxesSubplot at 0x104715160>
Похоже, есть кластер школ с высоким процентом женщин и очень высокими оценками ЕГЭ (справа вверху). Мы можем узнать названия школ этого кластера:
In [96]:
full[(full["female_per"] > 65) & (full["sat_score"] > 1400)]["School Name"]
Out[96]:
3 PROFESSIONAL PERFORMING ARTS HIGH SCH
92 ELEANOR ROOSEVELT HIGH SCHOOL
100 TALENT UNLIMITED HIGH SCHOOL
111 FIORELLO H. LAGUARDIA HIGH SCHOOL OF
229 TOWNSEND HARRIS HIGH SCHOOL
250 FRANK SINATRA SCHOOL OF THE ARTS HIGH SCHOOL
265 BARD HIGH SCHOOL EARLY COLLEGE
Name: School Name, dtype: object
Гугл нам объясняет, что это элитные школы, специализирующиеся на изобразительном искусстве. В этих школах больше процент женщин и выше оценки. Отсюда, скорее всего, корреляция между высоким процентом женщин и высокими оценками, и, наоборот, корреляция между высоким процентом мужчин и низкими оценками ЕГЭ.
Прим. перев.
Замечательная первая диаграмма наглядно демонстрирует нам, что в сумме процент мужчин и женщин должен быть в каждой школе 100 (ну или близок к нему).
Оценки по углубленной программе
До сего момента мы рассматривали демографические аспекты. Один аспект в данных, на который надо обратить внимание — это связь между большим числом студентов, сдавших углубленную программу, и высокими оценками ЕГЭ. Логично, что они должны коррелировать, поскольку ученики с более высокими желаниями в учёбе должны лучше сдавать ЕГЭ.
In [98]:
full["ap_avg"] = full["AP Test Takers "] / full["total_enrollment"]
full.plot.scatter(x='ap_avg', y='sat_score')
Out[98]:
<matplotlib.axes._subplots.AxesSubplot at 0x11463a908>
Похоже, между этими вещами сильная корреляция. Справа вверху есть интересный кластер школ с высокими оценками и высокой долей учеников, сдававших экзамен по УП:
In [99]:
full[(full["ap_avg"] > .3) & (full["sat_score"] > 1700)]["School Name"]
Out[99]:
92 ELEANOR ROOSEVELT HIGH SCHOOL
98 STUYVESANT HIGH SCHOOL
157 BRONX HIGH SCHOOL OF SCIENCE
161 HIGH SCHOOL OF AMERICAN STUDIES AT LE
176 BROOKLYN TECHNICAL HIGH SCHOOL
229 TOWNSEND HARRIS HIGH SCHOOL
243 QUEENS HIGH SCHOOL FOR THE SCIENCES A
260 STATEN ISLAND TECHNICAL HIGH SCHOOL
Name: School Name, dtype: object
Гугл показывает, что это достаточно требовательные школы, куда нужно сдать экзамен, чтобы попасть. Логично, что в этих школах много кто берёт углубленную программу.
Оформляем историю
В data science история никогда по-настоящему не заканчивается. Раскрывая анализ остальным, вы позволяете им расширять и формировать его в интересном им направлении. К примеру, в этом посте есть аспекты, которые мы исследовали не полностью, и в которые можно погрузиться глубже.
Один из отличных способов начать рассказывать истории с помощью данных — попытаться расширить или повторить чужой анализ. Если решите двигаться в этом направлении — можете расширять анализ этого поста и попробовать найти что-нибудь ещё. Если так — оставьте мне комментарий, чтобы я посмотрел.
Прим. перев.
Не мне, конечно, Вику. :)
Что дальше
Если вы добрались до сюда — у вас уже должно быть хорошее понимание того, как рассказывать историю через данные и как сделать первую работу для портфолио.
В Dataquest, у нас сделаны интерактивные обучающие проекты, чтобы вы начали делать своё портфолио для демонстрации его работодателям. Если интересно — можете подписаться и пройти первый модуль бесплатно.