This is a guided project from Dataquest.io and there are many like it, but this one is mine.
The purpose of this project is to explore how using the pandas plotting functionality along with Jupyter notebook allows us to explore data quickly using visualizations.
We'll be working with a dataset on the job outcomes of students who graduated from college between 2010 and 2012. The original data on job outcomes was released by American Community Survey, which conducts surveys and aggregates the data. FiveThirtyEight cleaned the dataset and released it on their Github repo.
Headers for recent-grads.csv are shown below:
| Header | Description | |:---------------------- |:---------------------------------------------------------------------------- | | Rank | Rank by median earnings | | Major_code | Major code, FO1DP in ACS PUMS | | Major | Major description | | Major_category | Category of major from Carnevale et al | | Total | Total number of people with major | | Sample_size | Sample size (unweighted) of full-time, year-round ONLY (used for earnings) | | Men | Male graduates | | Women | Female graduates | | ShareWomen | Women as share of total | | Employed | Number employed (ESR == 1 or 2) | | Full_time | Employed 35 hours or more | | Part_time | Employed less than 35 hours | | Full_time_year_round | Employed at least 50 weeks (WKW == 1) and at least 35 hours (WKHP >= 35) | | Unemployed | Number unemployed (ESR == 3) | | Unemployment_rate | Unemployed / (Unemployed + Employed) | | Median | Median earnings of full-time, year-round workers | | P25th | 25th percentile of earnings | | P75th | 75th percentile of earnings | | College_jobs | Number with job requiring a college degree | | Non_college_jobs | Number with job not requiring a college degree | | Low_wage_jobs | Number in low-wage service jobs |
After a quick inspection and cleaning of the dataset, we will move on to using various types of plots/visualizations to help answer questions like these:
Business
Humanities & Liberal Arts
Education
Engineering
Social Science
Business
Education
Humanities & Liberal Arts
Health
Psychology & Social Work
Business
Engineering
Humanities & Liberal Arts
Social Science
Computer Science & Mathematics
#load necessary libraries using conventional aliases
import pandas as pd
from pandas.plotting import scatter_matrix
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#read the file into a dataframe using pandas
recent_grads = pd.read_csv('recent-grads.csv')
Let's take a look at what we have! There are many ways to inspect a dataframe and below are just a few of the classics.
I like these (in this order) since it not only helps us to become familiar with the data itself but also helps in identifying any issues that we may need to address before moving on to any kind of data manipulation, analysis, or constructing plots.
#inspect the dataframe by looking at the first entry
recent_grads.iloc[0]
Rank 1 Major_code 2419 Major PETROLEUM ENGINEERING Total 2339 Men 2057 Women 282 Major_category Engineering ShareWomen 0.120564 Sample_size 36 Employed 1976 Full_time 1849 Part_time 270 Full_time_year_round 1207 Unemployed 37 Unemployment_rate 0.0183805 Median 110000 P25th 95000 P75th 125000 College_jobs 1534 Non_college_jobs 364 Low_wage_jobs 193 Name: 0, dtype: object
#inspect the dataframe by looking at the first five rows
recent_grads.head()
Rank | Major_code | Major | Total | Men | Women | Major_category | ShareWomen | Sample_size | Employed | ... | Part_time | Full_time_year_round | Unemployed | Unemployment_rate | Median | P25th | P75th | College_jobs | Non_college_jobs | Low_wage_jobs | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2419 | PETROLEUM ENGINEERING | 2339.0 | 2057.0 | 282.0 | Engineering | 0.120564 | 36 | 1976 | ... | 270 | 1207 | 37 | 0.018381 | 110000 | 95000 | 125000 | 1534 | 364 | 193 |
1 | 2 | 2416 | MINING AND MINERAL ENGINEERING | 756.0 | 679.0 | 77.0 | Engineering | 0.101852 | 7 | 640 | ... | 170 | 388 | 85 | 0.117241 | 75000 | 55000 | 90000 | 350 | 257 | 50 |
2 | 3 | 2415 | METALLURGICAL ENGINEERING | 856.0 | 725.0 | 131.0 | Engineering | 0.153037 | 3 | 648 | ... | 133 | 340 | 16 | 0.024096 | 73000 | 50000 | 105000 | 456 | 176 | 0 |
3 | 4 | 2417 | NAVAL ARCHITECTURE AND MARINE ENGINEERING | 1258.0 | 1123.0 | 135.0 | Engineering | 0.107313 | 16 | 758 | ... | 150 | 692 | 40 | 0.050125 | 70000 | 43000 | 80000 | 529 | 102 | 0 |
4 | 5 | 2405 | CHEMICAL ENGINEERING | 32260.0 | 21239.0 | 11021.0 | Engineering | 0.341631 | 289 | 25694 | ... | 5180 | 16697 | 1672 | 0.061098 | 65000 | 50000 | 75000 | 18314 | 4440 | 972 |
5 rows × 21 columns
#inspect the dataframe by looking at the last five rows
recent_grads.tail()
Rank | Major_code | Major | Total | Men | Women | Major_category | ShareWomen | Sample_size | Employed | ... | Part_time | Full_time_year_round | Unemployed | Unemployment_rate | Median | P25th | P75th | College_jobs | Non_college_jobs | Low_wage_jobs | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
168 | 169 | 3609 | ZOOLOGY | 8409.0 | 3050.0 | 5359.0 | Biology & Life Science | 0.637293 | 47 | 6259 | ... | 2190 | 3602 | 304 | 0.046320 | 26000 | 20000 | 39000 | 2771 | 2947 | 743 |
169 | 170 | 5201 | EDUCATIONAL PSYCHOLOGY | 2854.0 | 522.0 | 2332.0 | Psychology & Social Work | 0.817099 | 7 | 2125 | ... | 572 | 1211 | 148 | 0.065112 | 25000 | 24000 | 34000 | 1488 | 615 | 82 |
170 | 171 | 5202 | CLINICAL PSYCHOLOGY | 2838.0 | 568.0 | 2270.0 | Psychology & Social Work | 0.799859 | 13 | 2101 | ... | 648 | 1293 | 368 | 0.149048 | 25000 | 25000 | 40000 | 986 | 870 | 622 |
171 | 172 | 5203 | COUNSELING PSYCHOLOGY | 4626.0 | 931.0 | 3695.0 | Psychology & Social Work | 0.798746 | 21 | 3777 | ... | 965 | 2738 | 214 | 0.053621 | 23400 | 19200 | 26000 | 2403 | 1245 | 308 |
172 | 173 | 3501 | LIBRARY SCIENCE | 1098.0 | 134.0 | 964.0 | Education | 0.877960 | 2 | 742 | ... | 237 | 410 | 87 | 0.104946 | 22000 | 20000 | 22000 | 288 | 338 | 192 |
5 rows × 21 columns
#inspect the dataframe by way of statistical summaries on columns
recent_grads.describe()
Rank | Major_code | Total | Men | Women | ShareWomen | Sample_size | Employed | Full_time | Part_time | Full_time_year_round | Unemployed | Unemployment_rate | Median | P25th | P75th | College_jobs | Non_college_jobs | Low_wage_jobs | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 173.000000 | 173.000000 | 172.000000 | 172.000000 | 172.000000 | 172.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 | 173.000000 |
mean | 87.000000 | 3879.815029 | 39370.081395 | 16723.406977 | 22646.674419 | 0.522223 | 356.080925 | 31192.763006 | 26029.306358 | 8832.398844 | 19694.427746 | 2416.329480 | 0.068191 | 40151.445087 | 29501.445087 | 51494.219653 | 12322.635838 | 13284.497110 | 3859.017341 |
std | 50.084928 | 1687.753140 | 63483.491009 | 28122.433474 | 41057.330740 | 0.231205 | 618.361022 | 50675.002241 | 42869.655092 | 14648.179473 | 33160.941514 | 4112.803148 | 0.030331 | 11470.181802 | 9166.005235 | 14906.279740 | 21299.868863 | 23789.655363 | 6944.998579 |
min | 1.000000 | 1100.000000 | 124.000000 | 119.000000 | 0.000000 | 0.000000 | 2.000000 | 0.000000 | 111.000000 | 0.000000 | 111.000000 | 0.000000 | 0.000000 | 22000.000000 | 18500.000000 | 22000.000000 | 0.000000 | 0.000000 | 0.000000 |
25% | 44.000000 | 2403.000000 | 4549.750000 | 2177.500000 | 1778.250000 | 0.336026 | 39.000000 | 3608.000000 | 3154.000000 | 1030.000000 | 2453.000000 | 304.000000 | 0.050306 | 33000.000000 | 24000.000000 | 42000.000000 | 1675.000000 | 1591.000000 | 340.000000 |
50% | 87.000000 | 3608.000000 | 15104.000000 | 5434.000000 | 8386.500000 | 0.534024 | 130.000000 | 11797.000000 | 10048.000000 | 3299.000000 | 7413.000000 | 893.000000 | 0.067961 | 36000.000000 | 27000.000000 | 47000.000000 | 4390.000000 | 4595.000000 | 1231.000000 |
75% | 130.000000 | 5503.000000 | 38909.750000 | 14631.000000 | 22553.750000 | 0.703299 | 338.000000 | 31433.000000 | 25147.000000 | 9948.000000 | 16891.000000 | 2393.000000 | 0.087557 | 45000.000000 | 33000.000000 | 60000.000000 | 14444.000000 | 11783.000000 | 3466.000000 |
max | 173.000000 | 6403.000000 | 393735.000000 | 173809.000000 | 307087.000000 | 0.968954 | 4212.000000 | 307933.000000 | 251540.000000 | 115172.000000 | 199897.000000 | 28169.000000 | 0.177226 | 110000.000000 | 95000.000000 | 125000.000000 | 151643.000000 | 148395.000000 | 48207.000000 |
#inspect the dataframe by summary on dtypes and columns
recent_grads.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 173 entries, 0 to 172 Data columns (total 21 columns): Rank 173 non-null int64 Major_code 173 non-null int64 Major 173 non-null object Total 172 non-null float64 Men 172 non-null float64 Women 172 non-null float64 Major_category 173 non-null object ShareWomen 172 non-null float64 Sample_size 173 non-null int64 Employed 173 non-null int64 Full_time 173 non-null int64 Part_time 173 non-null int64 Full_time_year_round 173 non-null int64 Unemployed 173 non-null int64 Unemployment_rate 173 non-null float64 Median 173 non-null int64 P25th 173 non-null int64 P75th 173 non-null int64 College_jobs 173 non-null int64 Non_college_jobs 173 non-null int64 Low_wage_jobs 173 non-null int64 dtypes: float64(5), int64(14), object(2) memory usage: 28.5+ KB
#store original number of rows of the dataframe (173)
raw_data_count = recent_grads.shape[0]
The df.info()
method has revealed something interesting: our dataframe contains null values. Let's see what that's all about.
#display all rows with null values as a dataframe
recent_grads[recent_grads.isnull().any(axis=1)]
Rank | Major_code | Major | Total | Men | Women | Major_category | ShareWomen | Sample_size | Employed | ... | Part_time | Full_time_year_round | Unemployed | Unemployment_rate | Median | P25th | P75th | College_jobs | Non_college_jobs | Low_wage_jobs | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
21 | 22 | 1104 | FOOD SCIENCE | NaN | NaN | NaN | Agriculture & Natural Resources | NaN | 36 | 3149 | ... | 1121 | 1735 | 338 | 0.096931 | 53000 | 32000 | 70000 | 1183 | 1274 | 485 |
1 rows × 21 columns
Thankfully, the null values in our dataframe are confined to just the one row.
Since plotting often requires two variables with an equal number of values/observations for each, it is quite possible we end up throwing errors if we keep this row in our dataframe. Best to just drop it and keep going.
#remove rows containing null values
recent_grads.dropna(inplace=True)
cleaned_data_count = recent_grads.shape[0]
print('Difference in number of rows before and after cleaning:', raw_data_count - cleaned_data_count)
Difference in number of rows before and after cleaning: 1
Scatter plots are a great tool for visually inspecting data for relationships between two variables.
Things to look for in a scatter plot:
#scatter plot of 'Median vs. Total'
recent_grads.plot(x='Total', y='Median', kind='scatter', title= 'Median vs. Total')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa207f3e198>
Although there is a lot of variability in this scatter plot (i.e. correlation coefficient r
would be low in magnitude) it is clear that r
would also be negative. The trend becomes more clear as the total number of graduates with a particular degree increases; the median salary associated with that degree tends to decrease. Conversely, degrees with very few graduates can range from low median salaries to very high median salaries.
I'm not an economist but I believe the majority of this is following the simple rule of supply and demand.
Also, never forget human nature: some who graduate, do so with a degree that has a tendency to pay very little. Unfortunately, I believe this is where my personal data point is currently living. But I've "called in the movers" and DQ is helping!
#scatter plot of 'Median vs. ShareWomen'
recent_grads.plot(x= 'ShareWomen', y= 'Median', kind= 'scatter', title= 'Median vs. ShareWomen')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa207ead4a8>
Similar to the previous graph, the above graph shows that r
would be small but also clearly negative. This is a very discouraging observation. The trend suggests that the majors that are dominated by women tend to have a lower median salary.
So what does it show for the men? Since 'Men' + 'Women' = 'Total', the graph should simply be a flipped version (relection) of the one above. Let's generate that plot after adding a new column ShareMen
to our dataframe.
We will use the idea that: recent_grads['ShareWomen] + recent_grads['ShareMen'] = 1.0
in order to initialize and populate the new column with values.
recent_grads['ShareMen'] = 1 - recent_grads['ShareWomen']
recent_grads.plot(x= 'ShareMen', y= 'Median', kind= 'scatter', title= 'Median vs. ShareMen')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa207e4e400>
As we expected: it is a reflection of the graph above for women. Can someone remind me...what year is it again?! I wish I had some "time data" to plot in order to confirm this is a dying trend.
Since "money makes the world go 'round", we have decided to plot various observations against it to see what could possibly be influencing it.
#scatter plot of 'Median vs. Full_time'
recent_grads.plot(x= 'Full_time', y= 'Median', kind= 'scatter', title= 'Median vs. Full_time')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205e25d30>
#scatter plot of 'Median vs. Employed'
recent_grads.plot(x= 'Employed', y= 'Median', kind= 'scatter', title= 'Median vs. Employed')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205d95048>
#scatter plot of 'Median vs. Unemployed'
recent_grads.plot(x= 'Unemployed', y= 'Median', kind= 'scatter', title= 'Median vs. Unemployed')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205cf7080>
The three graphs above, with Median
on the y-axis, resemble our first graph of 'Median vs. Total'.
It appears that none of these relationships are particularly strong or very good for prediction, save for one scenario: a lot of people are involved (e.g. a lot of employed people --> low associated salary; a lot of full time eployees --> low associated salary). This matches with what we saw for students graduating with a popular major.
Ok, apart from the misogynistic chromosomal finding earlier, nothing is jumping out as being an influence on salary. What about just finding a job? What does our data say about that? Let's take a look!
#scatter plot of 'Employed vs. Total'
recent_grads.plot(x='Total', y='Employed', kind='scatter', title= 'Employed vs. Total')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205d85e48>
Now it looks like we've got something real! Clearly there is a strong positive correlation happening here; the more graduates we have with a particular degree, the more people are becoming employed. Sounds great! But beware the lurking variables...they like to lurk, so we need to look! Or, written in pythonic language: correlation != causation --> True.
#scatter plot of 'Unemployed vs. Total'
recent_grads.plot(x='Total', y='Unemployed', kind='scatter', title= 'Unemployed vs. Total')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205ce07f0>
Wait...huh? What just happened? Clearly not as strong of a positive correlation as the graph above it, but it is showing that as the total number of graduates increases, so does unemployment. That sounds bad and would seem to contradict what we thought was happening in the previous scatter plot. Let's take a look at one more before moving on to other visualizations.
#scatter plot of 'Employed vs. Unemployed'
recent_grads.plot(x='Unemployed', y='Employed', kind='scatter', title= 'Employed vs. Unemployed')
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205bacb00>
Ok, this just seems counter-intuitive: as the number of unemployed graduates with a particular degree increases, so too does the number of employed with the same degree?!
But if we take a moment to let that sink in and keeping in mind the one thing I know about economics (supply & demand) it begins to make sense because of the connection between Total
and Employed
|Unemployed
.
One of the reasons popular degrees are so popular is because they have good employment prospects. This creates the relationship we see between Total
and Employed
.
Supply and demand is then responsible for the relationship we see between Total
and Unemployed
.
Lastly, it is the transitive property of these metrics (i.e. a=b, b=c, therefore a=c) that is responsible for the pattern we see in 'Employed vs. Unemployed'.
Although they may look like simple bar charts (they aren't), histograms are best used when we want a visual representation of the frequency distribution of our data. They are great for comparing data with large value ranges.
Let's generate some plots and see what we can see!
ax = recent_grads['Sample_size'].hist(bins=45, range=(0,450))
ax.set_title('Sample Size Distribution')
print('Number of majors that used a Sample_size less than 450:',
recent_grads[recent_grads['Sample_size'] < 450].shape[0],
'out of', cleaned_data_count, '\n')
Number of majors that used a Sample_size less than 450: 141 out of 172
Because sample sizes vary so dramatically across the data, we have decided to shorten the range to approximately the bottom 10% of sample sizes in favour of graph readability. Although this a dramatic shortening of the data, it still accounts for 141/172 of our dataset.
The graph clearly shows a skew to the right which is a sign that the mean is higher than the median.
It also signals that the vast majority of the data were gathered using small sample sizes.
ax = recent_grads['Median'].hist(bins=50, range=(20000,110000))
ax.set_title('Median Salary Distribution')
print('Number of majors included in the graph:',
recent_grads[recent_grads['Median'].between(20000, 110000)].shape[0],
'out of', cleaned_data_count, '\n')
print('Number of majors with salary between $30,000 and $40,000:',
recent_grads[recent_grads['Median'].between(30000, 40000)].shape[0],
'out of', cleaned_data_count, '\n')
Number of majors included in the graph: 172 out of 172 Number of majors with salary between $30,000 and $40,000: 101 out of 172
Again we see a skew to the right due to that one salary above \$100,000. We can also see that the majority of salaries fall between \$30,000 and \$40,000 (101/172).
ax = recent_grads['Employed'].hist(bins=40, range=(0,60000))
ax.set_title('Employed Distribution')
print('Number of majors included in the graph:',
recent_grads[recent_grads['Employed'].between(0, 60000)].shape[0],
'out of', cleaned_data_count, '\n')
Number of majors included in the graph: 149 out of 172
Again, due to skewness, we have decided to shorten the range in favour of graph readability. As we've seen previously, most majors fall into the lower bins.
ax = recent_grads['ShareMen'].hist(bins=25, range=(0,1))
ax.set_title('Men Distribution')
print('Number of majors included in the graph:',
recent_grads[recent_grads['ShareMen'].between(0, 1)].shape[0],
'out of', cleaned_data_count, '\n')
Number of majors included in the graph: 172 out of 172
At first glance, it appears this distribution is quite even. However, upon closer inspection and modifying the number of bins
, we can clearly see that it is not completely so.
ax = recent_grads['ShareMen'].hist(bins=2, range=(0,1))
ax.set_title('Men Distribution')
print('Number of majors with Men in range:',
recent_grads[recent_grads['ShareMen'].between(0, 1)].shape[0],
'out of', cleaned_data_count, '\n')
print('Number of majors that are predominantly men:',
recent_grads[recent_grads['ShareMen'].between(0.5, 1)].shape[0],
'out of', cleaned_data_count, '\n')
Number of majors with Men in range: 172 out of 172 Number of majors that are predominantly men: 76 out of 172
Using only 2 bins
clearly shows less than half of all majors are predominantly comprised of men.
Specifically: 76 out of 172 majors are predominantly male.
ax = recent_grads['ShareWomen'].hist(bins=2, range=(0,1))
ax.set_title('Women Distribution')
print('Number of majors with Women in range:',
recent_grads[recent_grads['ShareWomen'].between(0, 1)].shape[0],
'out of', cleaned_data_count, '\n')
print('Number of majors that are predominantly women:',
recent_grads[recent_grads['ShareWomen'].between(0.5, 1)].shape[0],
'out of', cleaned_data_count, '\n')
Number of majors with Women in range: 172 out of 172 Number of majors that are predominantly women: 96 out of 172
Inversely, more than half of all majors are predominantly comprised of women.
Specifically: 96 out of 172 majors are predominantly female.
A scatter matrix plot combines both scatter plots and histograms into one grid of plots and allows us to explore potential relationships and distributions simultaneously.
A scatter matrix plot consists of n
by n
plots on a grid, where n
is the number of columns. The plots on the diagonal are histograms and the non-diagonal plots are scatter plots.
Scatter matrix plots are good for exploratory data analysis. They are great for when we want to quickly visualize distributions or discover relationships amongst multiple variables. Since this method returns a n
by n
plot, we must be careful not to pass too large of a dataframe or the output quickly becomes unreadable.
scatter_matrix(recent_grads[['Sample_size', 'Median']], figsize=(10,10))
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7fa2057522e8>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa2056454a8>], [<matplotlib.axes._subplots.AxesSubplot object at 0x7fa20560eef0>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa2055d1320>]], dtype=object)
scatter_matrix(recent_grads[['Sample_size', 'Median', 'Unemployment_rate']],
figsize=(10,10))
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7fa2054f4748>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa20546d4a8>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa205435cf8>], [<matplotlib.axes._subplots.AxesSubplot object at 0x7fa205718828>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa2057bdbe0>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa205774a20>], [<matplotlib.axes._subplots.AxesSubplot object at 0x7fa20585c978>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa2058040f0>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fa205a5b0b8>]], dtype=object)
Bar graphs are easy to understand, widely used, and can show changes over time. That gives them an advantage over other graphs that are difficult to read or can only show a single data set.
Most bar charts are plotted vertically, meaning the taller the bar the larger the category, but the data can be plotted horizontally instead meaning the longer the bar the larger the category. This is a good way to present data with long labels that would be hard to display below a vertical bar.
The first two bar graphs below clearly demonstrate this phenomenon. For this reason, we switched to horizontally plotted bar graphs for greater readability.
ax = recent_grads[:10].plot.bar(x='Major', y='ShareWomen', legend= False, title= 'ShareWomen vs. Major, top 10')
ax.set_ylabel('ShareWomen')
<matplotlib.text.Text at 0x7fa2058bbdd8>
ax = recent_grads[-10:].plot.bar(x='Major', y='ShareWomen', legend= False, title= 'ShareWomen vs. Major, bottom 10')
ax.set_ylabel('ShareWomen')
<matplotlib.text.Text at 0x7fa205adb1d0>
The above two graphs clearly show a gender bias when it comes to the selection of a major. Of the top ten majors (by median salary), only one is more than 50% female. Whereas of the bottom ten majors we see that every major is comprised of more than 50% female students.
ax = recent_grads[:10].plot.barh(x='Major', y='Unemployment_rate', legend= False,
title= 'Unemployment_rate vs. Major, top 10')
ax.set_xlabel('Unemployment_rate')
<matplotlib.text.Text at 0x7fa2059cb438>
ax = recent_grads[-10:].plot.barh(x='Major', y='Unemployment_rate', legend= False,
title= 'Unemployment_rate vs. Major, bottom 10')
ax.set_xlabel('Unemployment_rate')
<matplotlib.text.Text at 0x7fa2059894e0>
The above two graphs show that the unemployement rates for the top ten majors are, on average, lower than those of the bottom ten majors.
rg_grouped = recent_grads.groupby(["Major_category"])
ax = rg_grouped['Total'].sum().sort_values().plot(kind= 'barh')
ax.set_xlabel('Total Students')
ax.set_title('Total vs. Major_category')
#rg_grouped['Total'].sum().sort_values(ascending= False).head()
<matplotlib.text.Text at 0x7fa205336128>
The top five most popular categories for majors are:
Business
Humanities & Liberal Arts
Education
Engineering
Social Science
rg_grouped = recent_grads.groupby(["Major_category"])
ax = rg_grouped[['Women', 'Men']].sum().sort_values('Women').plot(kind= 'barh', figsize= (10, 8))
ax.set_xlabel('Total Students')
ax.set_ylabel('Category of Major, sorted by Women')
ax.set_title('Total vs. Major_category')
<matplotlib.text.Text at 0x7fa2056c8710>
rg_grouped = recent_grads.groupby(["Major_category"])
ax = rg_grouped[['Women', 'Men']].sum().sort_values('Men').plot(kind= 'barh', figsize= (10, 8))
ax.set_xlabel('Total Students')
ax.set_ylabel('Category of Major, sorted by Men')
ax.set_title('Total vs. Major_category')
<matplotlib.text.Text at 0x7fa20525f4e0>
The top five categories of majors chosen by women are:
Business
Education
Humanities & Liberal Arts
Health
Psychology & Social Work
The top five categories of majors chosen by men are:
Business
Engineering
Humanities & Liberal Arts
Social Science
Computer Science & Mathematics
Plotting data is fun! It also (quite litterally) gives us the ability to look at our data in many different ways. This is of tremendous help when we are trying to extract meaningful insights from a dataset. It's also just a great philosophy in life in general: try to see things from as many different angles as you can!
The plots that we have generated have helped us to realize:
Business
, Humanities & Liberal Arts
, Education
, Engineering
, and Social Science
Business
, Education
, Humanities & Liberal Arts
, Health
, and Psychology & Social Work
Business
, Engineering
, Humanities & Liberal Arts
, Social Science
, and Computer Science & Mathematics