Guided Project: Visualizing Earnings Based On College Majors

Section I: Introduction

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.

About the data

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

Where are we going with this?

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:

  • Do students in more popular majors make more money?
    • Using scatter plots
  • How many majors are predominantly male? Predominantly female?
    • Using histograms
  • Which category of majors have the most students?
    • Using bar plots

Summary of results

  • Students that majored in more popular subjects make less money.
  • 76 majors are predominantly male. 96 majors are predominantly female.
  • Men dominate the majors that are associated with higher median salaries
  • Women dominate the majors that are associated with lower median salaries
  • The majority of salaries are between \$30,000 and \\$40,000
  • Unemployment is lower in the top 10 majors (by median salary) than those in the bottom 10 majors
  • The most chosen majors by students are:
    • Business
    • Humanities & Liberal Arts
    • Education
    • Engineering
    • Social Science
  • The most chosen majors by women are:
    • Business
    • Education
    • Humanities & Liberal Arts
    • Health
    • Psychology & Social Work
  • The most chosen majors by men are:
    • Business
    • Engineering
    • Humanities & Liberal Arts
    • Social Science
    • Computer Science & Mathematics

Section II: Load, Look, and Clean

Loading...

We begin our adventure with setting up the environment by importing the libraries we need and running the necessary Jupyter magic so that plots are displayed inline.

In [1]:
#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')

Looking...

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.

In [2]:
#inspect the dataframe by looking at the first entry
recent_grads.iloc[0]
Out[2]:
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
In [3]:
#inspect the dataframe by looking at the first five rows
recent_grads.head()
Out[3]:
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

In [4]:
#inspect the dataframe by looking at the last five rows
recent_grads.tail()
Out[4]:
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

In [5]:
#inspect the dataframe by way of statistical summaries on columns
recent_grads.describe()
Out[5]:
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
In [6]:
#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
In [7]:
#store original number of rows of the dataframe (173)
raw_data_count = recent_grads.shape[0] 

Cleaning...

The df.info() method has revealed something interesting: our dataframe contains null values. Let's see what that's all about.

In [8]:
#display all rows with null values as a dataframe
recent_grads[recent_grads.isnull().any(axis=1)] 
Out[8]:
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.

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

Section III: Visualization of the Data

Scatter plots

Scatter plots are a great tool for visually inspecting data for relationships between two variables.

Things to look for in a scatter plot:

  • how changes in one variable affect the other
  • general trend as we read our data from left to right on the plot
  • clustering of data points
In [10]:
#scatter plot of 'Median vs. Total'
recent_grads.plot(x='Total', y='Median', kind='scatter', title= 'Median vs. Total')
Out[10]:
<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!

In [11]:
#scatter plot of 'Median vs. ShareWomen'
recent_grads.plot(x= 'ShareWomen', y= 'Median', kind= 'scatter', title= 'Median vs. ShareWomen')
Out[11]:
<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.

In [12]:
recent_grads['ShareMen'] = 1 - recent_grads['ShareWomen']
recent_grads.plot(x= 'ShareMen', y= 'Median', kind= 'scatter', title= 'Median vs. ShareMen')
Out[12]:
<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.

Median vs. various metrics

Since "money makes the world go 'round", we have decided to plot various observations against it to see what could possibly be influencing it.

In [13]:
#scatter plot of 'Median vs. Full_time'
recent_grads.plot(x= 'Full_time', y= 'Median', kind= 'scatter', title= 'Median vs. Full_time')
Out[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205e25d30>
In [14]:
#scatter plot of 'Median vs. Employed'
recent_grads.plot(x= 'Employed', y= 'Median', kind= 'scatter', title= 'Median vs. Employed')
Out[14]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fa205d95048>
In [15]:
#scatter plot of 'Median vs. Unemployed'
recent_grads.plot(x= 'Unemployed', y= 'Median', kind= 'scatter', title= 'Median vs. Unemployed')
Out[15]:
<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.

Employment status

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!

In [16]:
#scatter plot of 'Employed vs. Total'
recent_grads.plot(x='Total', y='Employed', kind='scatter', title= 'Employed vs. Total')
Out[16]:
<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.

In [17]:
#scatter plot of 'Unemployed vs. Total'
recent_grads.plot(x='Total', y='Unemployed', kind='scatter', title= 'Unemployed vs. Total')
Out[17]:
<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.

In [18]:
#scatter plot of 'Employed vs. Unemployed'
recent_grads.plot(x='Unemployed', y='Employed', kind='scatter', title= 'Employed vs. Unemployed')
Out[18]:
<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'.

Histograms

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!

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

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

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

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

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

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

Scatter Matrix Plots

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.

In [25]:
scatter_matrix(recent_grads[['Sample_size', 'Median']], figsize=(10,10))
Out[25]:
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)
In [26]:
scatter_matrix(recent_grads[['Sample_size', 'Median', 'Unemployment_rate']], 
               figsize=(10,10))
Out[26]:
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 Plots

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.

In [27]:
ax = recent_grads[:10].plot.bar(x='Major', y='ShareWomen', legend= False, title= 'ShareWomen vs. Major, top 10')
ax.set_ylabel('ShareWomen')
Out[27]:
<matplotlib.text.Text at 0x7fa2058bbdd8>
In [28]:
ax = recent_grads[-10:].plot.bar(x='Major', y='ShareWomen', legend= False, title= 'ShareWomen vs. Major, bottom 10')
ax.set_ylabel('ShareWomen')
Out[28]:
<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.

In [29]:
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')
Out[29]:
<matplotlib.text.Text at 0x7fa2059cb438>
In [30]:
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')
Out[30]:
<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.

In [31]:
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()
Out[31]:
<matplotlib.text.Text at 0x7fa205336128>

The top five most popular categories for majors are:

  • Business
  • Humanities & Liberal Arts
  • Education
  • Engineering
  • Social Science
In [32]:
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')
Out[32]:
<matplotlib.text.Text at 0x7fa2056c8710>
In [33]:
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')
Out[33]:
<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

Conclusion

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:

  • Men dominate the majors that are associated with higher median salaries
  • Women dominate the majors that are associated with lower median salaries
  • The majority of salaries are between \$30,000 and \\$40,000
  • Unemployment is lower in the top 10 majors (by median salary) than those in the bottom 10 majors
  • The most chosen majors by students are: Business, Humanities & Liberal Arts, Education, Engineering, and Social Science
  • The most chosen majors by women are: Business, Education, Humanities & Liberal Arts, Health, and Psychology & Social Work
  • The most chosen majors by men are: Business, Engineering, Humanities & Liberal Arts, Social Science, and Computer Science & Mathematics