Skytrax Data #4: The Logit Model
Skytrax Data #4: The Logit Model¶
We're going to quickly follow up on the OLS model presented in the last post with an alternative outcome variable: Whether or not passengers chose to recommend the airline to others.
import psycopg2
import pandas as pd
import numpy as np
from sqlalchemy import create_engine
import math
import statsmodels.api as sm
#This connects to the postgres database above.
connection = psycopg2.connect("dbname = skytrax user=skytraxadmin password=skytraxadmin")
cursor = connection.cursor()
connection.rollback()
cursor.execute('SELECT * from airline;')
data = cursor.fetchall()
data = pd.DataFrame(data)
descriptions = [desc[0] for desc in cursor.description]
data.columns = descriptions
In these data, "recommended" is coded as 1 and "not recommended" is coded as 0:
print len(data.loc[data['recommended'] == 1])
print len(data.loc[data['recommended'] == 0])
data.groupby(by = 'recommended').mean()
Unsurprisingly, ratings for flights that are recommended are higher than those that are not.
The logistic regression model¶
How do these ratings influence whether or not a passenger ultimately choses to recommend an airline to others? To find out, we can calculate the change in odds with each unit change in each variable. For example, for every point higher an airline scores on its overall rating, what is the probability that a passenger selected "1", would recommend, rather than "0"?
Again, we're going to ignore ground service ratings as well as wifi connectivity rating because the vast majority of cases have missing values on these variables.
The first thing we're going to do is center all our predictors. This, as we will see shortly, makes the constant interpretable, and is useful when trying to make point predictions (i.e., what are the odds that someone recommends an airline vs. not if he/she rated it an 8, for example).
predictors = ['overall_rating', 'seat_comfort_rating', 'cabin_staff_rating', 'food_beverages_rating', \
'inflight_entertainment_rating', 'value_money_rating']
for predictor in predictors:
data['{0}_centered'.format(predictor)] = data[predictor] - data[predictor].mean()
I ran two models, one that included passengers' overall ratings, and one that did not:
import statsmodels.api as sm
#x = data[['seat_comfort_rating', 'cabin_staff_rating', 'food_beverages_rating', \
# 'inflight_entertainment_rating', 'value_money_rating']]
x = data[['seat_comfort_rating_centered', 'cabin_staff_rating_centered',\
'food_beverages_rating_centered', 'inflight_entertainment_rating_centered', 'value_money_rating_centered']]
x = sm.add_constant(x)
logit = sm.Logit(data['recommended'], x, missing = 'drop') #drop missing values
results = logit.fit()
results.summary()
np.exp(results.params)
Interpreting the output¶
The coefficients of a logistic regression are in log odds, so to make them intuitively interpretable, we exponentiate them to get odds ratios. Odds ratios are simply the likelihood of one case over the other (in our case, it's the likelihood of recommending vs not).
The constant¶
The constant in this model is the predicted value (in this case, the predicted log odds) when all Xs = 0.
In this case, because we centered our variables at the mean, X=0 refers to the mean of that variable. Thus, our constant in this analysis refers to the odds of recommending vs not recommending for a hypothetical passenger who gave the airline mean ratings across the board. It's value, in this case, 1.06, tells us that this hypothetical passenger was 6% more likely to recommend than not. This is close to the unconditional (i.e., when we don't have any predictors) ratio of 14% (which is what you get when you divide the number of people who recommended vs not).
The coefficients¶
The coefficients in this model refer to the change in odds with each unit change for each variable. A value above one means that higher passenger ratings on that variable makes it more likely that a passenger recommends an airline. As one might expect, this was the case across the board here.
Let's look at a specific example: The coefficient of value for money, which is the largest here, tells us that, holding all other variables constant (i.e., for our hypothetical passenger that scored an airline the mean for everything), each unit change in value for money made it 3.8 times more likely (than the base rate of 6%) that he/she would recommend vs not.
Including passengers' overall ratings into the model¶
Next, we're going to look at a model that includes passengers' overall ratings:
#x = data[['overall_rating', 'seat_comfort_rating', 'cabin_staff_rating', 'food_beverages_rating', \
# 'inflight_entertainment_rating', 'value_money_rating']]
x = data[['overall_rating_centered', 'seat_comfort_rating_centered', 'cabin_staff_rating_centered',\
'food_beverages_rating_centered', 'inflight_entertainment_rating_centered', 'value_money_rating_centered']]
x = sm.add_constant(x)
logit = sm.Logit(data['recommended'], x, missing = 'drop') #drop missing values
results = logit.fit()
results.summary()
np.exp(results.params)
Including passengers' overall ratings substantially changed many of the coefficients. Let's go over the different parameters agian:
The constant¶
The constant for this model is now 2.48, which tells us that the hypothetical passenger who gave the airline the mean score on all ratings is now ~2.5 times more likely to recommend than not (contrast this to 1.06 in the previous model). What this implies is that an "average" in terms of an overall rating is really, on average, an endorsement of the airline.
The coefficients¶
Here, compared to the previous model, the coefficients for all the other ratings are "depressed", in they are much smaller than before. They are still positive, which means that in general, higher ratings on these criteria = more likely to recommend, but knowing a passenger's overall rating makes that information somewhat redundant.
Summary¶
In sum, when passengers are made to rate airlines this way, their decision to recommend is dominated by their overall, wholistic rating of the airline. That said, these ratings are all correlated, so the takeaway point should not be that inflight entertainment (which was a non-significant predictor even with an n of 28,000) is unimportant, but rather that further analyses should be done to assess the relative contribution of each predictor to a passenger's overall rating.