Exploring and Visualizing Earnings Based on College Majors

Executive Summary

In this report, we shall visualize and analyze data on the job outcomes of students who graduated from college between 2010 and 2012. The original data was released by American Community Survey, and was cleaned by FiveThirtyEight and released on their Github repo. Specifically, we will seek to answer questions on the relationships between student employment, unemployment, gender, major and other variables solely through visualization.

We find that student employment tended to be lower in majors related to the humanities, arts and education, and that these majors tended to have a higher percentage of women enrolled. We also find that women participation is highly volatile across majors, with shares of as little as 2% in majors related to Engineering and Science.

Note: This project is part of Data Quest's Data Scientist in Python track.

Setting up the environment

We begin by loading the required libraries.

In [16]:
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
from pandas.plotting import scatter_matrix

Reading in the dataset and initial overview

In [3]:
recent_grads = pd.read_csv('recent-grads.csv')
recent_grads.info()
recent_grads.head()
<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
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 [38]:
recent_grads.describe()
Out[38]:
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 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000 172.00000 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000 172.000000
mean 87.377907 3895.953488 39370.081395 16723.406977 22646.674419 0.522223 357.941860 31355.80814 26165.767442 8877.232558 19798.843023 2428.412791 0.068024 40076.744186 29486.918605 51386.627907 12387.401163 13354.325581 3878.633721
std 49.983181 1679.240095 63483.491009 28122.433474 41057.330740 0.231205 619.680419 50777.42865 42957.122320 14679.038729 33229.227514 4121.730452 0.030340 11461.388773 9190.769927 14882.278650 21344.967522 23841.326605 6960.467621
min 1.000000 1100.000000 124.000000 119.000000 0.000000 0.000000 2.000000 0.00000 111.000000 0.000000 111.000000 0.000000 0.000000 22000.000000 18500.000000 22000.000000 0.000000 0.000000 0.000000
25% 44.750000 2403.750000 4549.750000 2177.500000 1778.250000 0.336026 42.000000 3734.75000 3181.000000 1013.750000 2474.750000 299.500000 0.050261 33000.000000 24000.000000 41750.000000 1744.750000 1594.000000 336.750000
50% 87.500000 3608.500000 15104.000000 5434.000000 8386.500000 0.534024 131.000000 12031.50000 10073.500000 3332.500000 7436.500000 905.000000 0.067544 36000.000000 27000.000000 47000.000000 4467.500000 4603.500000 1238.500000
75% 130.250000 5503.250000 38909.750000 14631.000000 22553.750000 0.703299 339.000000 31701.25000 25447.250000 9981.000000 17674.750000 2397.000000 0.087247 45000.000000 33250.000000 58500.000000 14595.750000 11791.750000 3496.000000
max 173.000000 6403.000000 393735.000000 173809.000000 307087.000000 0.968954 4212.000000 307933.00000 251540.000000 115172.000000 199897.000000 28169.000000 0.177226 110000.000000 95000.000000 125000.000000 151643.000000 148395.000000 48207.000000

The dataset consists of 173 majors and 21 columns including information on the Rank (rank by median earnings), Major, Major Category, Total number of people with major, Sample Size, Number of male and female graduates, Number of employed graduates, Median salary, and other.

With the exception of Major and Major Category, columns are either an integer or float type. We also note that there are almost no null values.

Each row corresponds to all the information related to a particular Major as seen below, which is the case of Petroleum Engineering.

In [4]:
print('Petroleum Engineering overview')
recent_grads.iloc[0]
Petroleum Engineering overview
Out[4]:
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

Preparing the dataset for visualization

As we will be working with Matplotlib, we shall drop rows with missing values. This is because Matplotlib expects that columns of values passed in to have matching lengths.

In [5]:
raw_data_count = recent_grads.shape[0]
recent_grads = recent_grads.dropna()
cleaned_data_count = recent_grads.shape[0]
print('Cleaned data count: ', cleaned_data_count)
print('Raw data count: ', raw_data_count)
Cleaned data count:  172
Raw data count:  173

From the above, we can see that all null values corresponded to a single row so only one entry was dropped from our dataset.

Visualizing the dataset

Now that we've cleaned the dataset, we will explore relationships between various columns using a variety of plots.

Scatter plots

In [16]:
ax = recent_grads.plot(x='Total', y='Median', kind='scatter')
ax.set_title('Total number of graduates vs. Median')
Out[16]:
<matplotlib.text.Text at 0x7f509b8e0f98>

This first plot indicates that there is not a strong correlation between popularity of the major (as measured by number of graduates) and the median income of the student.

In [17]:
recent_grads.plot(x = 'Total', y = 'Unemployment_rate', kind = 'scatter',
                 title = 'Total number of graduates vs. Unemployment Rate')
Out[17]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b8d1f98>

In this previous plot one can see that there is no relationship between the popularity of the major and the unemployment rate within that major. This goes against theoretical relationships that one could think of, such as very popular majors having a higher unemployment rate due to a higher supply of graduates, but a lot of factors including high demand in those popular sectors is clearly resulting in a limited/null relationship between the two variables.

In [11]:
recent_grads.plot(x = 'Full_time', y = 'Median', kind = 'scatter',
                 title = 'Number of Full Time Workers vs. Median')
Out[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509bb00208>

This plot also showcases a lack of relationship between the number of full time workers and the median salary in that major.

In [12]:
recent_grads.plot(x = 'ShareWomen', y = 'Unemployment_rate', kind = 'scatter',
                 title = 'Share of Women vs. Unemployment Rate')
Out[12]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509bafa710>
In [15]:
recent_grads.plot(x = 'ShareWomen', y = 'Median', kind = 'scatter',
                 title = 'Share of women vs. Median')
Out[15]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b98ef28>

The previous two plots highlight that there is no correlation between participation of women in a major and the unemployment rate of graduates from that major. However, there is a slightly negative relationship between the participation of women in a major and the median salary in that major.

Histograms

As a next step, we will generate histograms to explore the distributions of several columns.

In [15]:
recent_grads['Sample_size'].hist(bins = 25)
plt.title('Histogram of sample size of graduates')
Out[15]:
Text(0.5, 1.0, 'Histogram of sample size of graduates')
In [26]:
recent_grads['Median'].hist(bins = 20)
plt.title('Histogram of median of graduates')
Out[26]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b253160>
In [20]:
recent_grads['Employed'].hist(bins = 25)
plt.title('Histogram of number of employed graduates per major')
Out[20]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b6caef0>
In [21]:
recent_grads['Full_time'].hist(bins = 25)
plt.title('Histogram of number of full time graduates per major')
Out[21]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b601be0>
In [29]:
recent_grads['ShareWomen'].hist(bins = 15)
plt.title('Histogram of women participation per major')
Out[29]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509afebda0>
In [23]:
recent_grads['Unemployment_rate'].hist(bins = 25)
plt.title('Histogram of unemployment rate of graduates per major')
Out[23]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b4a9f98>
In [24]:
recent_grads['Men'].hist(bins = 25)
plt.title('Histogram of number of male graduates per major')
Out[24]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b3df358>
In [25]:
recent_grads['Women'].hist(bins = 25)
plt.title('Histogram of number of female graduates per major')
Out[25]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f509b3019b0>

Some interesting highlights that one can observe in the previous histograms include the fact that the most common median salary range is USD30,000 - USD35,000, with only a minor amount of graduates earning a median salary of over USD80,000.

Additionally, one can observe that the share of women is relatively uniform between 0.2 and 0.8, indicating a high variance in the participation of women across majors.

The unemployment rate is centered around 6%, with a portion of majors having very high unemployment rates of over 12%.

Scatter Matrix Plots

Next, we will be using the scatter_matrix() function from the pandas.plotting module.

In [18]:
scatter_matrix(recent_grads[['Sample_size', 'Median']], figsize=(10,10))
plt.suptitle('Scatter matrix of sample size and graduate median per major')
Out[18]:
Text(0.5, 0.98, 'Scatter matrix of sample size and graduate median per major')
In [19]:
scatter_matrix(recent_grads[['Sample_size', 'Median', 'Unemployment_rate']], figsize=(10,10))
plt.suptitle('Scatter matrix of sample size, graduate median and unemployment rate per major')
Out[19]:
Text(0.5, 0.98, 'Scatter matrix of sample size, graduate median and unemployment rate per major')
In [20]:
scatter_matrix(recent_grads[['Men', 'Women', 'Total']], figsize=(10,10))
plt.suptitle('Scatter matrix of number of male, female and total graduates per major')
Out[20]:
Text(0.5, 0.98, 'Scatter matrix of number of male, female and total graduates per major')

With these scatter matrix plots, we can confirm our previous statements about the most common median salary range and unemployment rates. Moreover, we see that the median salary and the unemployment rate are largely uncorrelated.

Additionally, in terms of gender distribution, we can see that although the share of women in majors is highly variable across majors, the overall distribution of males and females is very similar, indicating that on aggregate participation of both genders is roughly the same. We can verify this by looking at the mean number of women and men in the recent_grads description generated in the overview, in which the mean number of women surpasses the mean number of men.

Bar Plots

We can take a closer look at the variance in the gender participation across majors using bar plots as follows.

In [21]:
recent_grads[:20].plot.bar(x='Major', y='ShareWomen')
plt.title('Participation of Women Across Majors - Engineering')
Out[21]:
Text(0.5, 1.0, 'Participation of Women Across Majors')

As the dataset is ordered by Major Category, we see that in the first 20 majors, which are from the Engineering category, female participation is overall quite low, particularly in Petroleum, Mining and Mineral, and Metallurgical Engineering.

In [22]:
recent_grads[-20:].plot.bar(x='Major', y='ShareWomen')
plt.title('Participation of Women Across Majors - Arts, Education and Humanities')
Out[22]:
Text(0.5, 1.0, 'Participation of Women Across Majors')

On the other hand, the last 20 rows are majors from the Biology & Life Science, Psychology & Social Work, Education, Arts, and Humanities categories. Here, we see a disproportionate amount of female participation, with women accounting for as much as almost 100% of graduates in majors such as Communication Disorders Sciences and Early Childhood Education.

Let us now take a look at the unemployment rate in these majors.

In [23]:
recent_grads[:20].plot.bar(x='Major', y='Unemployment_rate')
plt.title('Unemployment Rate Across Majors - Engineering')
Out[23]:
Text(0.5, 1.0, 'Unemployment Rate Across Majors')
In [24]:
recent_grads[-20:].plot.bar(x='Major', y='Unemployment_rate')
plt.title('Unemployment Rate Across Majors - Arts, Education and Humanities')
Out[24]:
Text(0.5, 1.0, 'Unemployment Rate Across Majors - Arts, Education and Humanities')

Overall, unemployment tends to be higher in the majors from the last twenty rows, that is, those relating to the humanities, arts and education, which also tend to have a higher participation of women.

These bar plots provide a more granular view of the trends that we noticed in the previous scatter plots and scatter matrix plots.

Conclusion

In this project, we used visualizations including scatter plots, bar plots and histograms to analyze relationships between variables related to job outcomes for graduates across a variety of majors. Using these visualizations, we were able to pinpoint interesting relationships and overall trends, including common ranges for the median salary and unemployment rate, and their differences across different groups including gender and major category.

In [ ]: