Les entreprises de Data Science se tournent de plus en plus vers les portfolios pour leurs processus d’embauche. Une des raisons à cela est qu’un portfolio est le meilleur moyen de juger des compétences réelles d’une personne. La bonne nouvelle pour vous, c’est qu’un portfolio dépend uniquement de vous. Si vous travaillez suffisamment, vous pourrez constituer un excellent portfolio avec des projets hétérogènes et passionnants qui impressionnera nombre d’entreprises.

La première étape pour créer un portfolio de grande qualité consiste à savoir quelles compétences vous devez démontrer. Les principales compétences recherchées par les entreprises dans le domaine des data sciences et donc les compétences qui doivent illustrer un portfolio sont les suivantes:

  • Capacité à communiquer
  • Capacité à collaborer avec les autres
  • Compétence technique
  • Capacité à raisonner sur les données
  • Motivation et capacité à prendre des initiatives

Tout bon portfolio sera composé de plusieurs projets, chacun d’eux pouvant démontrer 1 à 2 des points ci-dessus. Dans cet article, j’expliquerai comment réaliser votre premier projet pour un portfolio de Data Science et comment raconter une histoire efficace à l’aide de données. À la fin, vous aurez un projet qui aidera à démontrer votre capacité à communiquer et votre capacité à raisonner sur des données.

Storytelling avec des données

La Data Science concerne fondamentalement la communication. Vous découvrirez des informations dans les données puis vous découvrirez un moyen efficace de communiquer ces informations aux autres et enfin vous proposerez un plan d’action. L’une des compétences les plus critiques en Data Science est la capacité de raconter une histoire efficace à l’aide de données. Une histoire efficace peut rendre vos idées beaucoup plus convaincantes et surtout aider les autres à comprendre vos idées.

Une histoire dans le contexte de la Data Science est un récit autour de ce que vous avez trouvé, comment vous l’avez trouvé et ce que cela signifie. Un exemple pourrait être la découverte que les revenus de votre entreprise ont chuté de 20% au cours de la dernière année. Il ne suffit pas d’énoncer ce fait: vous devrez expliquer pourquoi les revenus ont chuté et comment les résoudre.

Les principales composantes de la narration avec des données sont les suivantes:

  • Compréhension et mise en contexte
  • Explorer plusieurs angles
  • Utiliser des visualisations convaincantes
  • Utilisation de sources de données variées
  • Avoir un récit cohérent

Le meilleur outil pour raconter efficacement une histoire avec des données est Jupyter Notebook. Jupyter notebook vous permet d’explorer des données de manière interactive, puis de partager vos résultats sur différents sites, y compris Github. Le partage de vos résultats est utile à la fois pour la collaboration et permet aux autres d’étendre votre analyse.

Dans cet article, nous utiliserons le notebook Jupyter, ainsi que les bibliothèques Python telles que Pandas et matplotlib.

Choisir un sujet pour votre projet de Data Science

La première étape dans la création d’un projet consiste à décider du sujet. Le sujet doit vous intéresser, vous devez être motivé à l’explorer en détail. C’est facile de savoir si la personne est vraiment intéressée ou non sur un projet en regardant son portfolio . Cela vaut la peine de passer plus de temps sur cette étape, alors assurez-vous de trouver quelque chose qui vous intéresse réellement.

Un bon moyen de trouver un sujet consiste à parcourir différents datasets et à voir ce qui semble intéressant. Pour déceler le dataset parfait, je vous invite à lire cet article: Les meilleurs datasets pour nos projets de Data Science.

Dans le monde de la Data Science, vous ne trouverez pas souvent un unique dataset permettant de réaliser votre projet en entier. Vous serez peut-être amener à agréger des sources de données disparates ou à effectuer une bonne quantité de nettoyage de données. Si un sujet vous intéresse beaucoup, choisissez le également car il sera le plus à même de montrer vos compétences.

Pour les besoins de cet article, nous utiliserons des données sur les écoles publiques de la ville de New York, qui peuvent être trouvées ici.

Choisir un sujet

Il est important de pouvoir mener le projet du début à la fin. Pour ce faire, il peut être utile de limiter la portée du projet afin d’être sur de pouvoir le terminer. Il est plus facile d’ajouter des éléments à un projet fini que de terminer un projet interminable.

Dans ce cas, nous examinerons les scores SAT des lycéens, ainsi que diverses informations démographiques et autres les concernant. Le SAT (ou Scholastic Aptitude Test) est un test que les lycéens passent aux États-Unis avant de postuler à l’université. Les universités prennent en compte les résultats des tests lors de la décision d’admission. Il est donc assez important de réussir. Le test est divisé en 3 sections, chacune étant notée sur 800 points. Le score total est sur 2400 (bien que cela ait changé quelques fois, les scores de ce dataset sont sur 2400). Les écoles secondaires sont souvent classées en fonction de leurs scores moyens au SAT. Des scores élevés au SAT sont considérées comme un signe de la qualité d’un district scolaire.

Il y a eu des rumeurs selon lesquelles la SAT serait injuste envers certains groupes raciaux aux États-Unis. Par conséquent, cette analyse des données de la ville de New York contribuera à faire la lumière sur l’équité de la SAT.

Nous avons ici un dataset contenant les scores SAT ici et un dataset contenant des informations sur chaque lycée ici. Celles-ci constitueront la base de notre projet, mais nous devrons ajouter plus d’informations pour créer une analyse convaincante.

Compléter l’apport des données

Une fois que vous avez un bon sujet, il est bon de définir d’autres datasets susceptibles de l’améliorer. C’est une bonne chose à faire dès le départ, afin d’avoir le plus de données possible à explorer lors de la construction de votre projet. Avoir trop peu de données peut signifier que vous n’attaquez pas votre projet avec suffisamment de profondeur.

Dans ce cas, plusieurs datasets connexes sur le même site Web couvrent les informations démographiques et les résultats des tests.

Voici les liens vers tous les datasets que nous utiliserons :

  • SAT scores by school – Scores SAT pour chaque lycée de New York.
  • School attendance – informations sur la fréquentation scolaire de chaque école de New York.
  • Math test results – résultats des tests de mathématiques de toutes les écoles de New York.
  • Class size – informations sur la taille de la classe pour chaque école de New York.
  • AP test results – Résultats de l’examen Advanced Placement (AP) pour chaque lycée. En passant des examens AP, vous pouvez obtenir un crédit universitaire aux États-Unis.
  • Graduation outcomes – pourcentage d’étudiants ayant obtenu leur diplôme et autres informations sur les résultats.
  • Demographics – informations démographiques pour chaque école.
  • School survey – enquêtes auprès des parents, des enseignants et des élèves de chaque école.
  • School district maps – contient des informations sur la disposition des districts scolaires, afin que nous puissions les cartographier.

Tous ces datasets sont interdépendants et nous pourrons les combiner avant toute analyse.

 

Obtenir des informations de base

Avant de plonger dans l’analyse des données, il est utile de rechercher des informations de base. Dans ce cas, nous connaissons quelques faits qui seront utiles:

  • La ville de New York est divisée en 5 quartiers, qui sont essentiellement des régions distinctes.
  • Les écoles à New York sont divisées en plusieurs districts scolaires, chacun pouvant contenir des dizaines d’écoles.
  • Toutes les écoles de tous datasets ne sont pas des lycées, nous devrons donc procéder à un nettoyage des données (data cleaning).
  • Chaque école à New York a un code unique appelé DBN (District Borough Number).
  • En agrégeant les données par district, nous pouvons utiliser les données de cartographie de district pour tracer les différences district par district.

 

Comprendre les données

Pour bien comprendre le contexte des données, vous devez passer du temps à les explorer et à les lire. Dans ce cas, chaque lien ci-dessus contient une description des données, ainsi que les colonnes correspondantes. Il semble que nous ayons des données sur les scores SAT des lycéens, ainsi que d’autres ensembles de données contenant des informations démographiques et autres.

Nous pouvons exécuter du code pour lire les données. Nous utiliserons Jupyter Notebook pour explorer les données. Le code ci-dessous va:

  • Parcourir chaque fichier de données que nous avons téléchargé.
  • Lire le fichier dans un DataFrame Pandas.
  • Placer chaque DataFrame dans un dictionnaire Python.
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

Une fois que nous avons lu les données, nous pouvons utiliser la méthode head sur nos DataFrames pour afficher rapidement les 5 premières lignes de chaque DataFrame:

for k,v in data.items():
    print("\n" + k + "\n")
    print(v.head())

 

math_test_results

DBNGradeYearCategoryNumber TestedMean Scale ScoreLevel 1 #\
001M01532006All Students396672
101M01532007All Students316722
201M01532008All Students376680
301M01532009All Students336680
401M01532010All Students266776
Level 1 %Level 2 #Level 2 %Level 3 #Level 3 %Level 4 #Level 4 %\
05.1%1128.2%2051.3%615.4%
16.5%39.7%2271%412.9%
20%616.2%2978.4%25.4%
30%412.1%2884.8%13%
423.1%1246.2%623.1%27.7%
Level 3+4 #Level 3+4 %
02666.7%
12683.9%
23183.8%
32987.9%
4830.8%

ap_2010

DBNSchoolNameAP Test TakersTotal Exams TakenNumber of Exams with scores 3 4 or 5
001M448UNIVERSITY NEIGHBORHOOD H.S.394910
101M450EAST SIDE COMMUNITY HS1921s
201M515LOWER EASTSIDE PREP242624
301M539NEW EXPLORATIONS SCI,TECH,MATH255377191
402M296High School of Hospitality Managementsss

sat_results

DBNSCHOOL NAMENum of SAT Test TakersSAT Critical Reading Avg. ScoreSAT Math Avg. ScoreSAT Writing Avg. Score
001M292HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES29355404363
101M448UNIVERSITY NEIGHBORHOOD HIGH SCHOOL91383423366
201M450EAST SIDE COMMUNITY SCHOOL70377402370
301M458FORSYTH SATELLITE ACADEMY7414401359
401M509MARTA VALLE HIGH SCHOOL44390433384

class_size

CSDBOROUGHSCHOOL CODESCHOOL NAMEGRADEPROGRAM TYPECORE SUBJECT (MS CORE and 9-12 ONLY)CORE COURSE (MS CORE and 9-12 ONLY)\
01MM015P.S. 015 Roberto Clemente0KGEN ED
11MM015P.S. 015 Roberto Clemente0KCTT
21MM015P.S. 015 Roberto Clemente01GEN ED
31MM015P.S. 015 Roberto Clemente01CTT
41MM015P.S. 015 Roberto Clemente02GEN E
SERVICE CATEGORY(K-9* ONLY)NUMBER OF STUDENTS / SEATS FILLEDNUMBER OF SECTIONSAVERAGE CLASS SIZESIZE OF SMALLEST CLASS\
019.01.019.019.0
121.01.021.021.0
217.01.017.017.0
317.01.017.017.0
415.01.015.015.0
SIZE OF LARGEST CLASSDATA SOURCESCHOOLWIDE PUPIL-TEACHER RATIO
019.0ATSNaN
121.0ATSNaN
217.0ATSNaN
317.0ATSNaN
415.0ATSNaN

demographics

DBNNameschoolyearfl_percentfrl_percent\
001M015P.S. 015 ROBERTO CLEMENTE2005200689.4NaN
101M015P.S. 015 ROBERTO CLEMENTE2006200789.4NaN
201M015P.S. 015 ROBERTO CLEMENTE2007200889.4NaN
301M015P.S. 015 ROBERTO CLEMENTE2008200989.4NaN
401M015P.S. 015 ROBERTO CLEMENTE2009201096.5
total_enrollmentprekkgrade1grade2black_numblack_per\
0281153640337426.3
1243152939386828.0
2261184339367729.5
3252173744327529.8
4208164028326732.2
hispanic_numhispanic_perwhite_numwhite_permale_nummale_perfemale_numfemale_per\
018967.351.8158.056.2123.043.8
115363.041.6140.057.6103.042.4
215760.272.7143.054.8118.045.2
314959.172.8149.059.1103.040.9
411856.762.9124.059.684.040.4

graduation

DemographicDBNSchool NameCohort\
0Total Cohort01M292HENRY STREET SCHOOL FOR INTERNATIONAL2003
1Total Cohort01M292HENRY STREET SCHOOL FOR INTERNATIONAL2004
2Total Cohort01M292HENRY STREET SCHOOL FOR INTERNATIONAL2005
3Total Cohort01M292HENRY STREET SCHOOL FOR INTERNATIONAL2006
4Total Cohort01M292HENRY STREET SCHOOL FOR INTERNATIONAL2006 Aug
Total CohortTotal Grads — nTotal Grads — % of cohortTotal Regents — n\
05sss
1553767.3%17
2644367.2%27
3784355.1%36
4784456.4%37
Total Regents — % of cohortTotal Regents — % of gradsRegents w/o Advanced — n\
0sss
130.9%45.9%17
242.2%62.8%27
346.2%83.7%36
447.4%84.1%37
Regents w/o Advanced — % of cohortRegents w/o Advanced — % of grads\
0ss
130.9%45.9%
242.2%62.8%
346.2%83.7%
447.4%84.1%
Local — nLocal — % of cohortLocal — % of grads Still Enrolled — n\
0ssss
12036.4%54.1%15
21625%37.200000000000003%9
379%16.3%16
479%15.9%15
Still Enrolled — % of cohortDropped Out — nDropped Out — % of cohort
0sss
127.3%35.5%
214.1%914.1%
320.5%1114.1%
419.2%1114.1%

hs_directory

dbnschool_nameboro\
017K548Brooklyn School for Music & TheatreBrooklyn
109X543High School for Violin and DanceBronx
209X327Comprehensive Model School Project M.S. 327Bronx
302M280Manhattan Early College School for AdvertisingManhattan
428Q680Queens Gateway to Health Sciences Secondary Sc…Queens
building_codephone_numberfax_numbergrade_span_mingrade_span_max\
0K440718-230-6250718-230-6262912
1X400718-842-0687718-589-9849912
2X240718-294-8111718-294-8109612
3M520718-935-3477NaN910
4Q695718-969-3155718-969-3552612
expgrade_span_minexpgrade_span_maxpriority02\
0NaNNaNThen to New York City residents
1NaNNaNThen to New York City residents who attend an …
2NaNNaNThen to Bronx students or residents who attend…
3914.0Then to New York City residents who attend an …
4NaNNaNThen to Districts 28 and 29 students or residents
priority03priority04priority05\
0NaNNaNNaN
1Then to Bronx students or residentsThen to New York City residentsNaN
2Then to New York City residents who attend an …Then to Bronx students or residentsThen to New York City residents
3Then to Manhattan students or residentsThen to New York City residentsNaN
4Then to Queens students or residentsThen to New York City residentsNaN
priority06priority07priority08priority09priority10Location 1
0NaNNaNNaNNaNNaN883 Classon Avenue\nBrooklyn, NY 11225\n(40.67…
1NaNNaNNaNNaNNaN1110 Boston Road\nBronx, NY 10456\n(40.8276026…
2NaNNaNNaNNaNNaN1501 Jerome Avenue\nBronx, NY 10452\n(40.84241…
3NaNNaNNaNNaNNaN411 Pearl Street\nNew York, NY 10038\n(40.7106…
4NaNNaNNaNNaNNaN160-20 Goethals Avenue\nJamaica, NY 11432\n(40…

 

Nous pouvons commencer à voir des motifs utiles dans nos datasets:

  • La plupart des datasets contiennent une colonne DBN
  • Certains champs semblent intéressants pour le mapping, notamment Location 1, qui contient des coordonnées entre autre.
  • Certains datasets semblent contenir plusieurs lignes pour chaque école (valeurs DBN répétées), ce qui signifie que nous devons les traiter au préalable.

 

Combiner les données

Afin de travailler plus facilement avec les données, nous devrons unifier tous les ensembles de données en un seul. Cela nous permettra de comparer rapidement les colonnes entre les différents datasets. Pour cela, nous devons d’abord trouver une colonne commune sur laquelle les combiner. En regardant le résultat ci-dessus, il apparaît que DBN pourrait être cette colonne commune, puisqu’elle apparaît dans plusieurs datasets.

Si nous recherchons sur Google DBN New York City Schools, on trouve ça, ce qui explique que le DBN est un code unique pour chaque école. Lors de l’exploration d’ensembles de données, en particulier de ceux du gouvernement, il est souvent nécessaire de faire un travail de détective pour déterminer la signification de chaque colonne, voire même son contenu.

On a un problème, c’est que deux des ensembles de données, class_size et hs_directory, ne possèdent pas ce champ DBN. Dans les données hs_directory, elle s’appelle simplement dbn, ouf! Nous pouvons donc renommer la colonne ou la copier dans une nouvelle colonne appelée DBN. Dans les données class_size, nous devrons tenter une approche différente.

La colonne DBN ressemble à ceci:

In [3]: data["demographics"]["DBN"].head()
Out[3]:
0    01M015
1    01M015
2    01M015
3    01M015
4    01M015
Name: DBN, dtype: object

Si nous regardons les données class_size, voici ce que nous verrions pour les 5 premières lignes:

In [4]:
data["class_size"].head()
Out[4]:

 

CSDBOROUGHSCHOOL CODESCHOOL NAMEGRADEPROGRAM TYPECORE SUBJECT (MS CORE and 9-12 ONLY)/
01MM015P.S. 015 Roberto Clemente0KGEN ED
11MM015P.S. 015 Roberto Clemente0KCTT
21MM015P.S. 015 Roberto Clemente01GEN ED
31MM015P.S. 015 Roberto Clemente01CTT
41MM015P.S. 015 Roberto Clemente02GEN ED

 

CORE COURSE (MS CORE and 9-12 ONLY)SERVICE CATEGORY(K-9* ONLY)NUMBER OF STUDENTS / SEATS FILLED/
019.0
121.0
217.0
317.0
415.0

 

NUMBER OF SECTIONSAVERAGE CLASS SIZESIZE OF SMALLEST CLASSSIZE OF LARGEST CLASSDATA SOURCESCHOOLWIDE PUPIL-TEACHER RATIO
01.019.019.019.0ATSNaN
11.021.021.021.0ATSNaN
21.017.017.017.0ATSNaN
31.017.017.017.0ATSNaN
41.015.015.015.0ATSNaN

 

Ajout des enquêtes

Comme vous pouvez le voir ci-dessus, il semble que le DBN soit en fait une combinaison de CSD, BOROUGH et SCHOOL CODE. Pour ceux qui ne connaissent pas New York, il est composé de 5 quartiers. Chaque quartier est une unité organisationnelle et a à peu près la même taille qu’une ville américaine assez grande. DBN signifie District Borough Number (Nombre de disctrict voisin). Il semble que le CSD soit le district, BOROUGH est le quartier et, une fois combiné avec le CODE SCHOOL, il forme le DBN. Il n’y a pas de moyen systématique de trouver des informations de ce type dans les données, et cela nécessite une pré-exploration et des manipulations pour le résoudre.

Maintenant que nous savons comment construire le DBN, nous pouvons l’ajouter aux datasets class_size et hs_directory:

In [5]:
data["class_size"]["DBN"] = data["class_size"].apply(lambda x: "{0:02d}{1}".format(x["CSD"], x["SCHOOL CODE"]), axis=1)
data["hs_directory"]["DBN"] = data["hs_directory"]["dbn"]

 

L’un des ensembles de données potentiellement les plus intéressants à examiner est l’ensemble de données sur les enquêtes auprès des élèves, des parents et des enseignants sur la qualité des écoles. Ces enquêtes incluent des informations sur la sécurité perçue de chaque école, les normes académiques, etc. Avant de combiner nos datasets, ajoutons les données de l’enquête. Dans les projets réels de Data Science, vous rencontrerez souvent des données intéressantes au milieu de votre analyse et voudrez les incorporer. Travailler avec un outil flexible tel que Jupyter Notebook vous permettra d’ajouter rapidement du code supplémentaire et de ré-exécuter votre analyse.

Dans ce cas, nous ajouterons les données de l’enquête dans notre dictionnaire data puis nous combinerons tous les datasets par la suite. L’enquête est constitué de 2 fichiers: un pour toutes les écoles et un pour le district scolaire 75. Nous devrons écrire du code pour les combiner.

Dans le code ci-dessous, nous allons:

  • Lire les sondages de toutes les écoles en utilisant l’encodage Windows-1252.
  • Lire les sondages des écoles du district 75 en utilisant l’encodage Windows-1252.
  • Préciser le district scolaire auquel chaque dataset est destiné.
  • Combiner les ensembles de données en un seul en utilisant la méthode concat sur les DataFrames.
In [6]:
survey1 = pandas.read_csv("schools/survey_all.txt", delimiter="\t", encoding='windows-1252')
survey2 = pandas.read_csv("schools/survey_d75.txt", delimiter="\t", encoding='windows-1252')
survey1["d75"] = False
survey2["d75"] = True
survey = pandas.concat([survey1, survey2], axis=0)

Une fois les enquêtes combinées, il y a une complication supplémentaire. Nous souhaitons minimiser le nombre de colonnes de notre ensemble de données combinées afin de pouvoir facilement comparer des colonnes et déterminer les corrélations.
Malheureusement, les données de l’enquête comportent de nombreuses colonnes qui ne nous sont pas très utiles:

In [7]:
survey.head()
Out[7]:

 

N_pN_sN_taca_p_11aca_s_11aca_t_11aca_tot_11/
090.0NaN22.07.8NaN7.97.9
1161.0NaN34.07.8NaN9.18.4
2367.0NaN42.08.6NaN7.58.0
3151.0145.029.08.57.47.87.9
490.0NaN23.07.9NaN8.18.0

 

bncom_p_11com_s_11t_q8c_1t_q8c_2t_q8c_3t_q8c_4/
0M0157.6NaN29.067.05.00.0
1M0197.6NaN74.021.06.00.0
2M0208.3NaN33.035.020.013.0
3M0348.25.921.045.028.07.0
4M0637.9NaN59.036.05.00.0

 

t_q9t_q9_1t_q9_2t_q9_3t_q9_4t_q9_5
0NaN5.014.052.024.05.0
1NaN3.06.03.078.09.0
2NaN3.05.016.070.05.0
3NaN0.018.032.039.011.0
4NaN10.05.010.060.015.0

5 rows × 2773 columns

Nous pouvons résoudre ce problème en consultant le fichier de dictionnaire de données que nous avons téléchargé avec les données de l’enquête. Le fichier nous indique les champs importants dans les données:

2011 NYC school survey

 

Nous pouvons alors supprimer toutes les colonnes superflues dans le sondage:

In [8]:
survey["DBN"] = survey["dbn"]
survey_fields = ["DBN", "rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_p_11", "com_p_11", "eng_p_11", "aca_p_11", "saf_t_11", "com_t_11", "eng_t_10", "aca_t_11", "saf_s_11", "com_s_11", "eng_s_11", "aca_s_11", "saf_tot_11", "com_tot_11", "eng_tot_11", "aca_tot_11",]
survey = survey.loc[:,survey_fields]
data["survey"] = survey
survey.shape
Out[8]:
(1702, 23)

En vous assurant de bien comprendre le contenu de chaque dataset et les colonnes (vraiment) pertinentes, vous gagnerez beaucoup de temps et limiterez vos efforts.

 

Datasets condensés

Si nous examinons certains des datasets, y compris class_size, nous verrons immédiatement un problème:

In [9]: data["class_size"].head()
Out[9]:

 

CSDBOROUGHSCHOOL CODESCHOOL NAMEGRADEPROGRAM TYPECORE SUBJECT (MS CORE and 9-12 ONLY)/
01MM015P.S. 015 Roberto Clemente0KGEN ED
11MM015P.S. 015 Roberto Clemente0KCTT
21MM015P.S. 015 Roberto Clemente01GEN ED
31MM015P.S. 015 Roberto Clemente01CTT
41MM015P.S. 015 Roberto Clemente02GEN ED

 

CORE COURSE (MS CORE and 9-12 ONLY)SERVICE CATEGORY(K-9* ONLY)NUMBER OF STUDENTS / SEATS FILLEDNUMBER OF SECTIONSAVERAGE CLASS SIZE/
019.01.019.0
121.01.021.0
217.01.017.0
317.01.017.0
415.01.015.0

 

SIZE OF SMALLEST CLASSSIZE OF LARGEST CLASSDATA SOURCESCHOOLWIDE PUPIL-TEACHER RATIODBN
019.019.0ATSNaN01M015
121.021.0ATSNaN01M015
217.017.0ATSNaN01M015
317.017.0ATSNaN01M015
415.015.0ATSNaN01M015

Sélectionnons uniquement les valeurs de class_size pour lesquelles le champ GRADE vaut 09-12.Il y a plusieurs lignes pour chaque lycée (comme vous pouvez le constater grâce aux champs DBN et SCHOOL NAME répétés). Cependant, si nous examinons l’ensemble de données sat_results, il ne contient qu’une seule ligne par lycée:

In [10]:
data["sat_results"].head()
Out[10]:

 

DBNSCHOOL NAMENum of SAT Test TakersSAT Critical Reading Avg. ScoreSAT Math Avg. ScoreSAT Writing Avg. Score
001M292HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES29355404363
101M448UNIVERSITY NEIGHBORHOOD HIGH SCHOOL91383423366
201M450EAST SIDE COMMUNITY SCHOOL70377402370
301M458FORSYTH SATELLITE ACADEMY7414401359
401M509MARTA VALLE HIGH SCHOOL44390433384

Afin de combiner ces datasets, nous devrons trouver un moyen de condenser des datasets tels que class_size au point de ne plus avoir qu’une seule ligne par lycée. Sinon, il ne sera pas possible de comparer les scores SAT à la taille de la classe. Nous pouvons y arriver en comprenant d’abord mieux les données, puis en procédant à une agrégation. Avec le dataset class_size, il semble que GRADE et PROGRAM TYPE aient plusieurs valeurs pour chaque école. En limitant chaque champ à une seule valeur, nous pouvons filtrer la plupart des lignes en double. Dans le code ci-dessous, nous:

  • Sélectionnons uniquement les valeurs de class_size pour lesquelles le champ PROGRAM TYPE vaut GEN ED.
  • Groupons le dataset class_size par DBN et prenons la moyenne de chaque colonne. Nous trouverons principalement les valeurs moyennes de class_size pour chaque école.
  • Réinitialisons l’index afin que la colonne DBN soit ajouté dans une colonne.
In [11]:
class_size = data["class_size"]
class_size = class_size[class_size["GRADE "] == "09-12"]
class_size = class_size[class_size["PROGRAM TYPE"] == "GEN ED"]
class_size = class_size.groupby("DBN").agg(np.mean)
class_size.reset_index(inplace=True)
data["class_size"] = class_size

 

Condenser d’autres datasets

Ensuite, nous devrons condenser le dataset demographics. Les données ont été collectées sur plusieurs années pour les mêmes écoles. Il existe donc des lignes en double pour chaque école. Nous ne sélectionnerons que les lignes pour lesquelles le champ schoolyear est le plus récent disponible:

In [12]:
demographics = data["demographics"]
demographics = demographics[demographics["schoolyear"] == 20112012]
data["demographics"] = demographics

Nous devrons condenser l’ensemble de données math_test_results. Cet ensemble de données est segmenté par grade (Grade) et par année (Year). Nous ne pouvons sélectionner qu’un seul grade pour une année donnée:

In [13]:
data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Year"] == 2011]
data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Grade"] ==

Enfin, le dataset graduation doit être condensé:

In [14]:
data["graduation"] = data["graduation"][data["graduation"]["Cohort"] == "2006"]
data["graduation"] = data["graduation"][data["graduation"]["Demographic"] == "Total Cohort"]

Le nettoyage et l’exploration des données sont essentiels avant de travailler sur le contenu du projet, ça correspond à 70% du métier. Avoir un bon ensemble de données cohérent vous aidera à faire votre analyse plus rapidement par la suite.

 

Quelques calculs sur les colonnes

Faire des calculs sur les colonnes peut accélérer notre analyse en nous permettant de faire des comparaisons plus rapidement. La première chose que nous pouvons faire est de calculer un score SAT total à partir des colonnes individuelles SAT Math Avg. Score, SAT Critical Reading Avg. Score et SAT Writing Avg. Score. Dans le code ci-dessous, nous:

  • Convertissons chacune des colonnes de score SAT: initialement ce sont des chaîne de caractères, nous les convertissons en nombre.
  • Additionnons toutes les colonnes pour obtenir la colonne sat_score, qui correspond au score SAT total.
In [15]:
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]]

Ensuite, nous devrons analyser les coordonnées de chaque école pour pouvoir créer des cartes. Cela nous permettra de tracer l’emplacement de chaque école. Dans le code ci-dessous, nous:

  • Analysons les latitudes et les longitudes de la colonne Location 1.
  • Convertissons les colonnes lat et lon en type numérique.
In [16]:
data["hs_directory"]['lat'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[0])
data["hs_directory"]['lon'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[1])

for c in ['lat', 'lon']:
    data["hs_directory"][c] = data["hs_directory"][c].convert_objects(convert_numeric=True)

 

Nous pouvons maintenant afficher nos données pour voir ce que nous avons:

In [17]:
for k,v in data.items():
    print(k)
    print(v.head())
Out [17]:

math_test_results

DBNGradeYearCategoryNumber TestedMean Scale Score\
11101M03482011All Students48646
28001M14082011All Students61665
34601M18482011All Students49727
38801M18882011All Students49658
41101M29282011All Students49650
Level 1 #Level 1 %Level 2 #Level 2 %Level 3 #Level 3 %Level 4 #\
1111531.3%2245.8%1122.9%0
28011.6%4370.5%1727.9%0
34600%00%510.2%44
3881020.4%2653.1%1020.4%3
4111530.6%2551%714.3%2
Level 4 %Level 3+4 #Level 3+4 %
1110%1122.9%
2800%1727.9%
34689.8%49100%
3886.1%1326.5%
4114.1%918.4%

survey

DBNrr_srr_trr_pN_sN_tN_psaf_p_11com_p_11eng_p_11\
001M015NaN8860NaN22.090.08.57.67.5
101M019NaN10060NaN34.0161.08.47.67.6
201M020NaN8873NaN42.0367.08.98.38.3
301M03489.07350145.029.0151.08.88.28.0
401M063NaN10060NaN23.090.08.77.98.1
eng_t_10aca_t_11saf_s_11com_s_11eng_s_11aca_s_11\
0NaN7.9NaNNaNNaNNaN
1NaN9.1NaNNaNNaNNaN
2NaN7.5NaNNaNNaNNaN
3NaN7.86.25.96.57.4
4NaN8.1NaNNaNNaNNaN
saf_tot_11com_tot_11eng_tot_11aca_tot_11
08.07.77.57.9
18.58.18.28.4
28.27.37.58.0
37.36.77.17.9
48.57.67.98.0

ap_2010

DBNSchoolNameAP Test TakersTotal Exams TakenNumber of Exams with scores 3 4 or 5
001M448UNIVERSITY NEIGHBORHOOD H.S.394910
101M450EAST SIDE COMMUNITY HS1921s
201M515LOWER EASTSIDE PREP242624
301M539NEW EXPLORATIONS SCI,TECH,MATH255377191
402M296High School of Hospitality Managementsss

sat_results

DBNSCHOOL NAMENum of SAT Test TakersSAT Critical Reading Avg. Score\
001M292HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES29355.0
101M448UNIVERSITY NEIGHBORHOOD HIGH SCHOOL91383.0
201M450EAST SIDE COMMUNITY SCHOOL70377.0
301M458FORSYTH SATELLITE ACADEMY7414.0
401M509MARTA VALLE HIGH SCHOOL44390.0
SAT Math Avg. ScoreSAT Writing Avg. Scoresat_score
0404.0363.01122.0
1423.0366.01172.0
2402.0370.01149.0
3401.0359.01174.0
4433.0384.01207.0

class_size

DBNCSDNUMBER OF STUDENTS / SEATS FILLEDNUMBER OF SECTIONS\
001M292188.00004.000000
101M332146.00002.000000
201M378133.00001.000000
301M4481105.68754.750000
401M450157.60002.733333
AVERAGE CLASS SIZESIZE OF SMALLEST CLASSSIZE OF LARGEST CLASSSCHOOLWIDE PUPIL-TEACHER RATIO
022.56428618.5026.571429NaN
122.00000021.0023.500000NaN
233.00000033.0033.000000NaN
322.23125018.2527.062500NaN
421.20000019.4022.866667NaN

demographics

DBNNameschoolyear\
601M015P.S. 015 ROBERTO CLEMENTE20112012
1301M019P.S. 019 ASHER LEVY20112012
2001M020PS 020 ANNA SILVER20112012
2701M034PS 034 FRANKLIN D ROOSEVELT20112012
3501M063PS 063 WILLIAM MCKINLEY20112012
fl_percentfrl_percenttotal_enrollmentprekkgrade1grade2\
6NaN89.418913313528
13NaN61.532832465254
20NaN92.56265210212187
27NaN99.740114343836
35NaN78.917618203021
black_numblack_perhispanic_numhispanic_perwhite_num\
66333.310957.74
138124.715848.228
20558.835757.016
279022.427568.68
354123.311062.515
white_permale_nummale_perfemale_numfemale_per
62.197.051.392.048.7
138.5147.044.8181.055.2
202.6330.052.7296.047.3
272.0204.050.9197.049.1
358.597.055.179.044.9

graduation

DemographicDBNSchool NameCohort\
3Total Cohort01M292HENRY STREET SCHOOL FOR INTERNATIONAL2006
10Total Cohort01M448UNIVERSITY NEIGHBORHOOD HIGH SCHOOL2006
17Total Cohort01M450EAST SIDE COMMUNITY SCHOOL2006
24Total Cohort01M509MARTA VALLE HIGH SCHOOL2006
31Total Cohort01M515LOWER EAST SIDE PREPARATORY HIGH SCHO2006
Total CohortTotal Grads — nTotal Grads — % of cohortTotal Regents — n\
3784355.1%36
101245342.7%42
17907077.8%67
24844756%40
3119310554.4%91
Total Regents — % of cohortTotal Regents — % of gradsRegents w/o Advanced — n\
346.2%83.7%36
1033.9%79.2%34
1774.400000000000006%95.7%67
2447.6%85.1%23
3147.2%86.7%22
Regents w/o Advanced — % of cohortRegents w/o Advanced — % of grads\
346.2%83.7%
1027.4%64.2%
1774.400000000000006%95.7%
2427.4%48.9%
3111.4%21%
Local — nLocal — % of cohortLocal — % of gradsStill Enrolled — n\
379%16.3%16
10118.9%20.8%46
1733.3%4.3%15
2478.300000000000001%14.9%25
31147.3%13.3%53
Still Enrolled — % of cohortDropped Out — nDropped Out — % of cohort
320.5%1114.1%
1037.1%2016.100000000000001%
1716.7%55.6%
2429.8%56%
3127.5%3518.100000000000001%

hs_directory

dbnschool_nameboro\
017K548Brooklyn School for Music & TheatreBrooklyn
109X543High School for Violin and DanceBronx
209X327Comprehensive Model School Project M.S. 327Bronx
302M280Manhattan Early College School for AdvertisingManhattan
428Q680Queens Gateway to Health Sciences Secondary Sc…Queens
building_codephone_numberfax_numbergrade_span_mingrade_span_max\
0K440718-230-6250718-230-6262912
1X400718-842-0687718-589-9849912
2X240718-294-8111718-294-8109612
3M520718-935-3477NaN910
4Q695718-969-3155718-969-3552612
expgrade_span_minexpgrade_span_maxpriority05priority06priority07priority08\
0NaNNaNNaNNaNNaNNaN
1NaNNaNNaNNaNNaNNaN
2NaNNaNThen to New York City residentsNaNNaNNaN
3914.0NaNNaNNaNNaN
4NaNNaNNaNNaNNaNNaN
priority09priority10Location 1\
0NaNNaN883 Classon Avenue\nBrooklyn, NY 11225\n(40.67…
1NaNNaN1110 Boston Road\nBronx, NY 10456\n(40.8276026…
2NaNNaN1501 Jerome Avenue\nBronx, NY 10452\n(40.84241…
3NaNNaN411 Pearl Street\nNew York, NY 10038\n(40.7106…
4NaNNaN160-20 Goethals Avenue\nJamaica, NY 11432\n(40…
DBNlatlon
017K54840.670299-73.961648
109X54340.827603-73.904475
209X32740.842414-73.916162
302M28040.710679-74.000807
428Q68040.718810-73.806500

Combiner les datasets

Maintenant que nous avons effectué toutes les étapes préliminaires, nous pouvons combiner les datasets à l’aide de la colonne DBN. À la fin, nous aurons un dataset avec des centaines de colonnes contenant chacun les datasets d’origine. Lorsque nous les combinons, il est important de noter que certains ensembles de données n’ont pas tous tous les établissements d’enseignement secondaire que l’on trouve dans l’ensemble de données sat_results. Pour résoudre ce problème, nous devrons fusionner les datasets contenant des lignes manquantes à l’aide de la stratégie de jointure externe afin de ne pas perdre de données (outer join). Sur des cas concrets réels, il est fréquent que des données soient manquantes. Etre capable de démontrer la capacité de raisonner et de gérer les données manquantes est un élément important de la construction d’un portfolio (en vu d’être recruté).

Si vous souhaitez en savoir plus sur les différents types de jointure, voici la doc officielle ici.

Dans le code ci-dessous, nous allons:

  • Parcourir chacun des éléments du dictionnaire data.
  • Afficher le nombre de DBNs non uniques pour chaque élément.
  • Décider d’une stratégie de jointure – inner ou outer.
  • Joindre l’élément au DataFrame full à l’aide de la colonne DBN.
In [18]:
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[18]:
(374, 174)

 

Ajouter des valeurs

Maintenant que nous avons notre DataFrame full, nous avons presque toutes les informations dont nous avons besoin pour faire notre analyse. Il manque cependant quelques pièces. Nous pouvons vouloir corréler les résultats de l’examen Advanced Placement (AP) avec les scores SAT, mais nous devrons d’abord convertir ces colonnes en nombre, puis compléter les valeurs manquantes:

In [19]:
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)

 

Ensuite, nous devrons calculer une colonne school_dist qui indique le district scolaire de l’école. Cela nous permettra de faire correspondre les districts scolaires et d’établir des statistiques au niveau du district à l’aide des cartes de district que nous avons téléchargées précédemment:

In [20]:
full["school_dist"] = full["DBN"].apply(lambda x: x[:2])

 

Enfin, nous devrons compléter toutes les valeurs manquantes avec la moyenne de la colonne afin de pouvoir calculer les corrélations:

In [21]:
full = full.fillna(full.mean())

Faire des corrélations

Un bon moyen d’explorer un dataset et de voir quelles colonnes sont liées entre elles est de faire des corrélations. Cela vous indiquera quelles colonnes sont étroitement liées à la colonne qui vous intéresse. Nous pouvons le faire via la méthode corr sur les DataFrames Pandas. Plus la corrélation est proche de 0, plus la connexion est faible. Plus on se rapproche de 1, plus la corrélation positive est forte et plus on se rapproche de -1, plus la corrélation négative est forte:

In [22]:
full.corr()['sat_score']
Out[22]:
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

 

Cela nous donne quelques idées que nous devrons explorer plus en détail:

  • Le nombre total d’inscriptions est fortement corrélé avec sat_score, ce qui est surprenant, car on pourrait penser que les écoles plus petites, plus axées sur l’élève, obtiennent des scores plus élevés.
  • Le pourcentage de jeunes femmes dans une école (female_per) est positivement corrélé avec le score SAT, alors que le pourcentage de jeunes hommes (male_per) est en corrélation négative.
  • Aucune des réponses à l’enquête ne présente une forte corrélation avec les scores SAT.
  • Il existe une inégalité raciale significative dans les scores SAT (white_per, asian_per, black_per, hispanic_per).
  • ell_percent est fortement corrélé négativement avec les scores SAT.

Chacun de ces éléments constitue un angle potentiel pour explorer et raconter une histoire sur l’utilisation des données.

 

Mise en contexte

Avant de nous lancer dans l’exploration des données, nous souhaitons définir le contexte, tant pour nous-mêmes que pour quiconque lisant notre analyse. Une bonne façon de faire est d’utiliser des cartes ou des graphiques. Dans ce cas, nous allons tracer les positions des écoles, ce qui aidera les lecteurs à comprendre le problème que nous explorons.

Dans le code ci-dessous, nous:

  • Configurons une carte centrée sur la ville de New York.
  • Ajoutons un marqueur sur la carte pour chaque lycée de la ville.
  • Affichons la carte.
In [23]:
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[23]:

Construire un portfolio de Data Science: Raconter une histoire

Cette carte est utile, mais il est difficile de voir où se trouvent la plupart des écoles à New York. Au lieu de cela, nous ferons une carte thermique:

In [24]:
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[24]:

Construire un portfolio de Data Science: Raconter une histoire

Cartographie au niveau du district

Les cartes thermiques sont utiles pour cartographier les gradients, mais nous voudrons un système plus structuré pour calculer les différences de score SAT à travers la ville. Les districts scolaires sont un bon moyen de visualiser ces informations car chaque district a sa propre administration. La ville de New York compte plusieurs douzaines de districts scolaires et chaque district est une petite zone géographique.

Nous pouvons calculer le score SAT par district scolaire, puis le tracer sur une carte. Dans le code ci-dessous, nous allons:

  • Grouper full par district scolaire.
  • Calculer la moyenne de chaque colonne pour chaque district scolaire.
  • Convertir le champ school_dist pour supprimer les 0 afin que nous puissions faire correspondre nos données de district géographique.
In [25]:
district_data = full.groupby("school_dist").agg(np.mean)
district_data.reset_index(inplace=True)
district_data["school_dist"] = district_data["school_dist"].apply(lambda x: str(int(x))

 

Nous allons maintenant pouvoir tracer le score SAT moyen dans chaque district scolaire. Pour ce faire, nous allons lire les données au format GeoJSON pour obtenir les formes de chaque district, puis associer chaque forme de district au score SAT à l’aide de la colonne school_dist, puis créer le graphique suivant:

In [26]:
def show_district_map(col):
    geo_path = 'schools/districts.geojson'
    districts = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
    districts.geo_json(
        geo_path=geo_path,
        data=district_data,
        columns=['school_dist', col],
        key_on='feature.properties.school_dist',
        fill_color='YlGn',
        fill_opacity=0.7,
        line_opacity=0.2,
    )
    districts.save("districts.html")
    return districts

show_district_map("sat_score")
Out[26]:

Construire un portfolio de Data Science: Raconter une histoire

Exploration des inscriptions et des scores SAT

Maintenant que nous avons défini le contexte en traçant l’emplacement des écoles et le score SAT par district, les personnes consultant notre analyse ont une meilleure idée du contexte de l’ensemble de données. Maintenant que nous avons préparé le terrain, nous pouvons explorer les angles que nous avons identifiés plus tôt, lorsque nous trouvions des corrélations. Le premier angle à explorer est la relation entre le nombre d’élèves inscrits dans une école et le score SAT.

Nous pouvons explorer cela avec un diagramme de dispersion qui compare le nombre total d’inscriptions aux scores SAT dans toutes les écoles.

In [27]:
%matplotlib inline

full.plot.scatter(x='total_enrollment', y='sat_score')
Out[27]:
<matplotlib.axes._subplots.AxesSubplot at 0x10fe79978>

Construire un portfolio de Data Science: Raconter une histoire

Comme vous pouvez le constater, un groupe en bas à gauche présente un nombre total d’inscriptions faible et un score SAT faible. Hormis ce groupe, il ne semble exister qu’une légère corrélation positive entre les scores SAT et le nombre total d’inscriptions. La représentation graphique des corrélations peut révéler des modèles inattendus.

Nous pouvons explorer cela davantage en obtenant les noms des écoles ayant un faible taux d’inscription et de faibles scores au SAT:

In [28]:
full[(full["total_enrollment"] < 1000) & (full["sat_score"] < 1000)]["School Name"]
Out[28]:
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

 

Certaines recherches sur Google montrent que la plupart de ces écoles sont destinées aux étudiants qui apprennent l’anglais et que, par conséquent, leur nombre d’inscriptions est faible. Cette exploration nous a montré que ce n’est pas le nombre total d’élèves qui est corrélé au score SAT, mais bien le fait que les étudiants de l’école apprennent ou non l’anglais comme seconde langue.

 

Explorer les apprenants d’anglais et les scores SAT

Maintenant que nous savons que le pourcentage d’apprenants d’anglais dans une école est en corrélation avec des scores SAT inférieurs, nous pouvons explorer la relation. La colonne ell_percent représente le pourcentage d’élèves de chaque école qui apprennent l’anglais. Nous pouvons faire un diagramme de dispersion de cette relation:

In [29]:
full.plot.scatter(x='ell_percent', y='sat_score')
Out[29]:
<matplotlib.axes._subplots.AxesSubplot at 0x10fe824e0>

Construire un portfolio de Data Science: Raconter une histoire

Il semble qu’il existe un groupe d’écoles (avec un pourcentage ell_percentage élevé) qui présentent également des scores SAT moyens faibles. Nous pouvons étudier cela au niveau du district, en déterminant le pourcentage d’apprenants en anglais dans chaque district et en le vérifiant s’il correspond à notre carte des scores SAT par district:

In [30]:
show_district_map("ell_percent")
Out[30]:

Construire un portfolio de Data Science: Raconter une histoire

Comme nous pouvons le constater en consultant les cartes au niveau des deux districts, les districts avec une faible proportion d’apprenants ELL ont tendance à avoir des scores SAT élevés, et inversement.

 

Corrélation des scores d’enquête et des scores SAT

Il serait juste de supposer que les résultats des sondages auprès des élèves, des parents et des enseignants auraient une forte corrélation avec les scores SAT. Il est logique que les écoles ayant des attentes académiques élevées, par exemple, aient tendance à avoir des scores SAT plus élevés. Pour tester cette théorie, calculons les scores SAT et les différentes mesures de l’enquête:

In [31]:
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[31]:
<matplotlib.axes._subplots.AxesSubplot at 0x114652400>

Construire un portfolio de Data Science: Raconter une histoire

Étonnamment, les deux facteurs les plus corrélés sont N_p et N_s, qui sont les comptes des parents et des élèves qui ont répondu au sondage. Les deux sont fortement corrélés avec le nombre total d’inscriptions et sont donc probablement biaisés par les ell_learners. L’autre mesure qui est le plus corrélée est saf_t_11. C’est ainsi que les élèves, les parents et les enseignants ont considéré l’école comme étant sûre. Il est logique que plus l’école est sûre, plus les élèves se sentent à l’aise d’apprendre dans cet environnement. Cependant, aucun des autres facteurs, tels que l’engagement, la communication et les attentes académiques, n’est en corrélation avec les scores SAT. Cela peut indiquer que NYC pose les mauvaises questions dans les sondages ou réfléchit aux mauvais facteurs (si l’objectif est d’améliorer les scores au SAT, ce n’est peut-être pas le cas).

 

Explorer l’origine et les scores SAT

L’un des autres angles à examiner concerne l’origine et les scores SAT. Il y avait un grand différentiel de corrélation, et le tracer nous aidera à comprendre ce qui se passe:

In [32]:
full.corr()["sat_score"][["white_per", "asian_per", "black_per", "hispanic_per"]].plot.bar()
Out[32]:
<matplotlib.axes._subplots.AxesSubplot at 0x108166ba8>

Construire un portfolio de Data Science: Raconter une histoire

Il semble que les pourcentages plus élevés d’élèves blancs et asiatiques soient en corrélation avec des scores plus élevés au SAT, mais des pourcentages plus élevés d’élèves noirs et hispaniques sont en corrélation avec des scores au plus bas SAT. Pour les étudiants hispaniques, cela peut être dû au fait qu’il y a de plus en plus d’immigrants récents apprenants ELL. Nous pouvons mapper le pourcentage hispanique par district pour observer la corrélation:

In [33]:
show_district_map("hispanic_per")
Out[33]:

Construire un portfolio de Data Science: Raconter une histoire

Il semble y avoir une certaine corrélation avec le pourcentage ELL, mais il sera nécessaire de creuser un peu plus cette différence et même d’autres différences raciales dans les scores SAT.

 

Différences entre les sexes dans les scores SAT

Le dernier angle à explorer est la relation entre le sexe et le score SAT. Nous avons constaté qu’un pourcentage plus élevé de filles dans une école tend à être en corrélation avec des scores SAT plus élevés. Nous pouvons le visualiser avec un graphique à barres:

In [34]:
full.corr()["sat_score"][["male_per", "female_per"]].plot.bar()
Out[34]:
<matplotlib.axes._subplots.AxesSubplot at 0x10774d0f0>

Construire un portfolio de Data Science: Raconter une histoire

Pour creuser davantage la corrélation, nous pouvons créer un diagramme de dispersion de female_per et sat_score:

In [35]:
full.plot.scatter(x='female_per', y='sat_score')
Out[35]:
<matplotlib.axes._subplots.AxesSubplot at 0x104715160>

Construire un portfolio de Data Science: Raconter une histoire

Il semble qu’il existe un groupe d’écoles avec un pourcentage élevé de filles et des scores très élevés au SAT (en haut à droite). Nous pouvons obtenir les noms des écoles de ce groupe:

In [36]:
full[(full["female_per"] > 65) & (full["sat_score"] > 1400)]["School Name"]
Out[36]:
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

 

La recherche sur Google révèle qu’il s’agit d’écoles d’élites qui se concentrent sur les arts de la scène. Ces écoles ont tendance à avoir des pourcentages plus élevés de filles et de meilleurs scores au SAT. Cela explique probablement la corrélation entre les pourcentages féminins les plus élevés et les scores au SAT, et la corrélation inverse entre les pourcentages masculins les plus élevés et les scores au SAT inférieurs.

 

Scores AP

Jusqu’ici, nous avons examiné les angles démographiques. On peut examiner la relation entre davantage d’élèves prenant des examens Advanced Placement (AP) et des scores plus élevés au SAT. Il est logique qu’ils soient corrélés, car les étudiants très performants ont tendance à mieux réussir à la SAT.

In [37]:
full["ap_avg"] = full["AP Test Takers "] / full["total_enrollment"]

full.plot.scatter(x='ap_avg', y='sat_score')
Out[37]:
<matplotlib.axes._subplots.AxesSubplot at 0x11463a908>

Construire un portfolio de Data Science: Raconter une histoire

Il semble en effet qu’il existe une forte corrélation entre les deux. Un groupe d’écoles intéressant est celui situé en haut à droite, qui présente des scores SAT élevés et une forte proportion d’élèves ayant passé les examens AP:

In [38]:
full[(full["ap_avg"] > .3) & (full["sat_score"] > 1700)]["School Name"]
Out[38]:
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

Certaines recherches sur Google ont révélé que ce sont pour la plupart des écoles très sélectives dans lesquelles vous devez passer un test. Il est donc logique que ces écoles aient un pourcentage élevé de candidats au test AP.

 

Continuer l’histoire…

Avec la Data Science, l’histoire n’est jamais vraiment terminée. En diffusant l’analyse aux autres, vous leur permettez d’étendre et de façonner votre analyse dans la direction qui les intéresse. Par exemple, dans cet article, il y a pas mal d’angles que nous avons explorés de manière incomplète, et nous aurions pu nous y plonger davantage.

L’un des meilleurs moyens de commencer à raconter des histoires à l’aide de données est d’essayer d’étendre ou de reproduire l’analyse effectuée par quelqu’un d’autre. Si vous décidez de suivre cette voie, n’hésitez pas à approfondir l’analyse présentée dans cet article et à voir ce que vous pouvez trouver. Si vous le faites, faites moi signe et montrez moi vos recherches 🙂

 

Prochaines étapes

Si vous en êtes arrivé là, vous avez tout pour bien comprendre comment raconter une histoire avec des données et comment créer votre premier projet d’un portfolio de Data Science. Vous êtes sur la bonne voie, accrochez-vous !