Happy individual

In Four Ways of Thinking our friends switch focus.

../../_images/HappyIndividual.png

The specific question we look at here is this: Imagine, after you have paid your bills, you have more than $200 per month to spend divided between three categories: (1) material items, (2) experiences and (3) time-saving services. How should you spend this money in order to be as happy as possible? We try to answer this question using a questionnaire conducted by Whillans et al. (2017). We look in particular at 1067 people with varying incomes, but all with a budget of at least $200 to spend. The study participants typically spent about $250 on (each of) material items and experiences, and about half as much on time-saving.

All the participants were asked the question:

Please imagine a ladder with steps numbered from zero at the bottom to ten at the top.
Suppose we say that the top of the ladder represents the best possible life for you
and the bottom of the ladder represents the worst possible life for you.
On which step of the ladder would you say you personally feel you stand at this time?

This is how see Whillans et al. measure happiness in the study I write about in the book. In this section we dig in to the data of the replies they received in one of the studies they conducted as part of their work.

Loading in the data

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
import statsmodels.formula.api as smf
import random

from pylab import rcParams
rcParams['figure.figsize'] = 12/2.54, 12/2.54


# Find people who spent more than 200 dollars in total
# These are the people we will look at in this study.

# The data file we use here is a adapted from the data from here https://osf.io/vr9pa/
# Study 7 US Qualtrics data.
df=pd.read_csv('../data/spending.csv')

morethan200=df['spent_on_MATA']+df['spent_on_TSA']+df['spent_on_EXPA'] >200
df=df[morethan200]

print('The average happiness score was %.2f.' % np.mean(df['Happiness']))
print('The standard deviation in happiness score was %.2f.' %np.std(df['Happiness']))
print('90 percent of people had a happiness score of %.2f or more.' % np.quantile(df['Happiness'],0.9))
print('10 percent of people had a happiness score of %.2f or less.' % np.quantile(df['Happiness'],0.1))
The average happiness score was 7.15.
The standard deviation in happiness score was 1.84.
90 percent of people had a happiness score of 10.00 or more.
10 percent of people had a happiness score of 5.00 or less.

Try it yourself!

Think about the answer you would give to this question now. By putting yourself in the participants shoes you can better understand what it means when people rank their happiness.

The participants gave a wide-range of answers, with an average of 7.15, but scores as low as 3 and as high as 10 were not untypical.

Spending money on saving time

Let’s start by looking at the difference in average happiness. Are people who spend money on saving time happier?

didspend=df['spent_on_TSA']>0
didntspend=df['spent_on_TSA']<=0
mean_did= np.mean(df['Happiness'][didspend])
mean_didnt= np.mean(df['Happiness'][didntspend])

print('The average happiness score for those who spent on time-saving was %.2f.' % mean_did)
print('The average happiness score for those who did not spent on time-saving was %.2f.' % mean_didnt)

std_did=np.nanstd(df['Happiness'][didspend])
n_did=len(df['Happiness'][didspend])
std_didnt=np.nanstd(df['Happiness'][didntspend])
n_didnt=len(df['Happiness'][didntspend])
cohensd=(mean_did-mean_didnt)/np.sqrt(((n_did-1)*std_did**2+(n_didnt-1)*std_didnt**2)/(n_did+n_didnt-2))

print('The Cohens D for this difference is %.2f' % cohensd)
The average happiness score for those who spent on time-saving was 7.43.
The average happiness score for those who did not spent on time-saving was 6.63.
The Cohens D for this difference is 0.44

Cohen’s D is a statistic for measuring effect size. How big an effect does spending on time saving have? An effect of 0.44 is considered to be medium.

The difference between the two groups can’t be attributed to chance, since over one thousand people were surveyed, but it is not a particularly large difference. But it is not particularly large. This point is illustrated below in a histogram for those who did spend money on time saving (top in the figure below) and those who did not (bottom in the figure below).

def FormatFigure(ax):
    ax.legend(loc='upper left')
    ax.set_ylim(0,0.32)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.set_ylabel('')
    ax.set_xlabel('Average Happiness (0-10)')
    ax.set_ylabel('Proportion of people')
    ax.set_xticks(np.arange(0,11,step=1))


fig,(ax1,ax2)=plt.subplots(2,1)
ax1.hist(df['Happiness'][didspend], np.arange(0.01,10.5,1), color='orange', edgecolor = 'black',linestyle='-',alpha=0.5, label='Spent on saving time', density=True,align='right')
FormatFigure(ax1)
ax2.hist(df['Happiness'][didntspend], np.arange(0.01,10.5,1), alpha=0.5, edgecolor = 'black', label='Did not spend on saving time',  density=True,align='right')
FormatFigure(ax2)

plt.show()
plot happyperson

What is most striking is how little these two histograms differ, with those not spending money of time-saving shifted very slightly to the left. There are more tens in the did spend group, but otherwise they are not that different.

In the code below we pick pairs of people at random - one from thosee who did spend on time-saving and one person who didn’t spend on time-saving. We then look at the proportion of times the one who did spend on time-saving is happier.

df_did=df['Happiness'][didspend]
df_didnt=df['Happiness'][didntspend]
rand_did=df_did.sample(10000,replace=True)
rand_didnt=df_didnt.sample(10000,replace=True)
print('The person who did spend on time-saving is happiest %.2f percent of times.' % (np.mean(np.array(rand_did)>np.array(rand_didnt))*100))
The person who did spend on time-saving is happiest 55.12 percent of times.

If you currently do not spend any of your budget on time-saving, then this value of around 55% gives an estimate of the probability you would be happier if you did. Likewise, if you currently do spend some of your budget on time-saving, then the probability you would be happier if you didn’t make the spend is 45%.

In the book I let the friends explain:

../../_images/FriendsExplain.png

It thus makes sense to spend money on time-saving, but results are by no means guaranteed.

What to spend money on

How much happier can we expect to be per dollar spent on, respectively, material items, experiences and time-saving?

To answer this question, we plot average happiness against the amount of money people spent.

# The data is coded for different spending levels.
# This converts the spending levels in to dollars.
scale_spending = np.array([0] + list(range(10,100,20)) + list(range(150,1000,100)) + [1000] + [1000])
scale_spending = np.append(scale_spending, [np.nan,np.nan,np.nan])
scale_spending_labels = {0.0: '$0',
 1.0: '$1-$19',
 2.0: '$20-$39',
 3.0: '$40-$59',
 4.0: '$60-$79',
 5.0: '$80-$99',
 6.0: '$100-$199',
 7.0: '$200-$299',
 8.0: '$300-$399',
 9.0: '$400-$499',
 10.0: '$500-$599',
 11.0: '$600-$699',
 12.0: '$700-$799',
 13.0: '$800-$899',
 14.0: '$900-$999',
 15.0: '$1000-$2500',
 16.0: 'More than $2500'}

rcParams['figure.figsize'] = 14/2.54, 10/2.54

fig,axs=plt.subplots(2,2)

for i,original_name in enumerate(['MATA','EXPA','TSA','Bills']):

    mean_happy = np.zeros(len(scale_spending))*np.nan
    std_happy = np.zeros(len(scale_spending))*np.nan
    num_value = np.zeros(len(scale_spending))*np.nan

    #Measure happiness for each
    for j,lb in enumerate(np.unique(scale_spending)):
        dfs=df[df['spent_on_' + original_name]==lb]
        num_value[j]=len(dfs)
        if len(dfs)>5:
            mean_happy[j]=np.nanmean(dfs['Happiness'])
            std_happy[j]=np.nanstd(dfs['Happiness'])/np.sqrt(len(dfs))

    ax=axs[int(np.ceil(i/2))-1][np.remainder(i,2)]

    #Plot the graph.
    ax.scatter(scale_spending, mean_happy,s=(num_value/4)+1)
    print(mean_happy)

    ax.set_ylim(5,10)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    if i==0:
        ax.text(0,9,'Material purchases', fontsize=11)
        ax.set_ylabel('Average Happiness')
        ax.set_xlabel('Spent per month')
    if i==1:
        ax.text(0,9,'Experiences \nand entertainment', fontsize=11)
    if i==2:
        ax.text(0,9,'Time saving \nand eating out', fontsize=11)
        ax.set_ylabel('Average Happiness')
    if i==3:
        ax.text(0,9,'Paying bills', fontsize=11)
        ax.set_xlabel('Spent per month')
    ax.set_xticks(np.arange(0,1100,step=250))
    ax.set_xticklabels(['$0','$250','$500','$750','$1000+'])

plt.show()
plot happyperson
[6.80952381        nan        nan 7.23333333 6.93913043 7.12264151
 6.69291339 7.         7.07086614 7.24390244 7.66666667 8.18604651
 8.47368421 7.9        8.35294118 8.53846154        nan        nan
        nan        nan]
[6.69565217        nan        nan 6.33333333 6.3442623  6.88095238
 7.41732283 6.94217687 7.26771654 7.43333333 7.48717949 8.03125
 8.25       8.33333333 8.125      8.95833333        nan        nan
        nan        nan]
[6.63172043 7.44444444 6.66       6.93589744 7.21505376 7.54929577
 7.30555556 7.56896552 7.27586207 8.13043478 8.45454545 7.73684211
 8.17391304 8.6875     8.61538462 8.36363636        nan        nan
        nan        nan]
[       nan 6.66666667 6.92857143 6.72727273 6.60869565 7.08450704
 6.97727273 6.82352941 7.28846154 7.01282051 7.10798122 7.04724409
 7.45985401 7.12962963 7.16981132 7.49180328        nan        nan
        nan        nan]

We see that those with the most money to spend are the happiest. Those with expenditure of $1000 per month on each of material, experiences and time-saving have a happiness of around 8.5 on average. Paying bills does not make people happier.

We would all love to have $1000 to spend on each of the three categories, but what is the best investment on a limited budget?

Here it is important to notice that time-saving initially increases faster per dollar spent than the lines for material purchases or experiences. We can estimate how more rapid this increase is using linear regression, which measures the steepness of the increase for each factor.

model_fit=smf.ols(formula='Happiness' + ' ~  spent_on_MATA + spent_on_TSA + spent_on_EXPA + spent_on_Bills' , data=df).fit()
print(model_fit.summary())

print('For every $100 spent per month on time saving, %.2f points of happiness gained' % (100.0*model_fit.params['spent_on_TSA']))
print('For every $100 spent per month on experiences, %.2f points of happiness gained' % (100.0*model_fit.params['spent_on_EXPA']))
print('For every $100 spent per month on material purchases, %.2f points of happiness gained' % (100.0*model_fit.params['spent_on_MATA']))
                            OLS Regression Results
==============================================================================
Dep. Variable:              Happiness   R-squared:                       0.098
Model:                            OLS   Adj. R-squared:                  0.094
Method:                 Least Squares   F-statistic:                     28.73
Date:                Tue, 03 Sep 2024   Prob (F-statistic):           1.08e-22
Time:                        07:11:26   Log-Likelihood:                -2107.6
No. Observations:                1067   AIC:                             4225.
Df Residuals:                    1062   BIC:                             4250.
Df Model:                           4
Covariance Type:            nonrobust
==================================================================================
                     coef    std err          t      P>|t|      [0.025      0.975]
----------------------------------------------------------------------------------
Intercept          6.4082      0.128     49.897      0.000       6.156       6.660
spent_on_MATA      0.0007      0.000      2.840      0.005       0.000       0.001
spent_on_TSA       0.0013      0.000      4.630      0.000       0.001       0.002
spent_on_EXPA      0.0011      0.000      4.154      0.000       0.001       0.002
spent_on_Bills  9.137e-05      0.000      0.482      0.630      -0.000       0.000
==============================================================================
Omnibus:                       33.304   Durbin-Watson:                   1.959
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               35.612
Skew:                          -0.438   Prob(JB):                     1.85e-08
Kurtosis:                       3.180   Cond. No.                     1.86e+03
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.86e+03. This might indicate that there are
strong multicollinearity or other numerical problems.
For every $100 spent per month on time saving, 0.13 points of happiness gained
For every $100 spent per month on experiences, 0.11 points of happiness gained
For every $100 spent per month on material purchases, 0.07 points of happiness gained

This method tells us that for every $100 spent in different ways how much happiness is gained. So, increasing spending from $0 per month to around $500 per month on saving time (if you have that money to spare) would make you almost 0.13*5 = 0.65 point (on a scale of 0 to 10) happier.

In the book I write that “[Antony] finds that every $100 spent on time-saving leads to an average gain of 0.31 points on the happiness scale. So, increasing spending from $0 per month to around $300 per month on saving time provides almost one extra point of happiness. “

This claim is based on a regression model that includes a non-linear term to capture the saturation at high levels of spending. I repeat the regression with squared terms as follows.

for original_name in ['MATA','Bills','TSA','EXPA']:
    variable_of_interest='spent_on_' + original_name
    df[variable_of_interest + '_2']=df[variable_of_interest]**2

model_fit=smf.ols(formula='Happiness' + ' ~  spent_on_MATA + spent_on_TSA + spent_on_EXPA + spent_on_MATA_2 + spent_on_TSA_2 + spent_on_EXPA_2' , data=df).fit()
print(model_fit.summary())
                            OLS Regression Results
==============================================================================
Dep. Variable:              Happiness   R-squared:                       0.104
Model:                            OLS   Adj. R-squared:                  0.099
Method:                 Least Squares   F-statistic:                     20.45
Date:                Tue, 03 Sep 2024   Prob (F-statistic):           9.73e-23
Time:                        07:11:26   Log-Likelihood:                -2104.0
No. Observations:                1067   AIC:                             4222.
Df Residuals:                    1060   BIC:                             4257.
Df Model:                           6
Covariance Type:            nonrobust
===================================================================================
                      coef    std err          t      P>|t|      [0.025      0.975]
-----------------------------------------------------------------------------------
Intercept           6.3403      0.158     40.160      0.000       6.031       6.650
spent_on_MATA       0.0006      0.001      0.757      0.449      -0.001       0.002
spent_on_TSA        0.0031      0.001      4.119      0.000       0.002       0.005
spent_on_EXPA       0.0014      0.001      2.049      0.041    5.77e-05       0.003
spent_on_MATA_2  3.042e-07   8.34e-07      0.365      0.715   -1.33e-06    1.94e-06
spent_on_TSA_2  -2.319e-06    9.1e-07     -2.549      0.011    -4.1e-06   -5.34e-07
spent_on_EXPA_2 -4.064e-07   7.71e-07     -0.527      0.598   -1.92e-06    1.11e-06
==============================================================================
Omnibus:                       35.731   Durbin-Watson:                   1.968
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               38.455
Skew:                          -0.455   Prob(JB):                     4.46e-09
Kurtosis:                       3.188   Cond. No.                     1.06e+06
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.06e+06. This might indicate that there are
strong multicollinearity or other numerical problems.

Notice that spending time on time saving This analysis is further supported by the following graph, which looks at how happiness depends on the proportion of money spent on saving time for people who spend more than $200 per month on the three categories.

df['Prop_TS']=df['spent_on_TSA']/(df['spent_on_MATA']+df['spent_on_TSA']+df['spent_on_EXPA'] )
df['Prop_EXP']=df['spent_on_EXPA']/(df['spent_on_MATA']+df['spent_on_TSA']+df['spent_on_EXPA'] )
df['Prop_MATA']=df['spent_on_MATA']/(df['spent_on_MATA']+df['spent_on_TSA']+df['spent_on_EXPA'] )



rcParams['figure.figsize'] = 16/2.54, 10/2.54

scale_of_interest=np.append(np.arange(0,0.71,0.1), 1.0)
fig,axs=plt.subplots(1,3)

axs[0].set_ylabel('Average Happiness (0-10)')

for j,variable_of_interest in enumerate(['Prop_TS', 'Prop_EXP', 'Prop_MATA']):

    ax=axs[j]
    mean_happy = np.zeros(len(scale_of_interest)-1)
    std_happy = np.zeros(len(scale_of_interest)-1)
    num_value = np.zeros(len(scale_of_interest)-1)
    for i,lb in enumerate(scale_of_interest[:-1]):
        lbp1=scale_of_interest[i+1]
        dfs=df[np.logical_and(df[variable_of_interest]>=lb,df[variable_of_interest]<lbp1)]
        mean_happy[i]=np.mean(dfs['Happiness'])
        std_happy[i]=np.std(dfs['Happiness'])/np.sqrt(len(dfs))
        num_value[i]=len(dfs)

    ax.scatter(scale_of_interest[:-1], mean_happy,s=num_value)

    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.set_xlim(-0.05,0.75)
    ax.set_ylim(6,9)


    ax.set_xticks(np.arange(0,0.8,step=0.2))
    ax.set_xticklabels(['0%','20%','40%','60%'  ])

    if j==2:
        ax.text(0,8.3,'Material purchases', fontsize=11)
    if j==1:
        ax.text(0,8.3,'Experiences \nand entertainment', fontsize=11)
        ax.set_xlabel('Percentage spending')

    if j==0:
        ax.text(0,8.3,'Time saving \nand eating out', fontsize=11)

plt.show()
plot happyperson

Happiness reaches a maximum at around 20% to 30% spending on time-saving and on experiences and entertainment. Using too much of your budget to buy material items leads to a decrease in happiness.

Remeber that the size of the circles are the proportion of people in that category We can calulate

print('The average person spend %.2f percent of their budget on time saving' % (100.0*np.mean(df['Prop_TS'])))
print('The average person spend %.2f percent of their budget on experiences' % (100.0*np.mean(df['Prop_EXP'])))
print('The average person spend %.2f percent of their budget on material purchases' % (100.0*np.mean(df['Prop_MATA'])))
The average person spend 17.11 percent of their budget on time saving
The average person spend 39.77 percent of their budget on experiences
The average person spend 43.12 percent of their budget on material purchases

This suggests that most of us could benefit from increasing our spending on time saving.

Summary: If you currently spend very little on money on time-saving today then investing between $100 and $300 can probably make you a fair bit happier. Spending on experiences is less effective, and spending on material purchases is not effective.

Causation

Can we say that time-saving purchases cause us to become happier? And, if so, what should I buy!?!?

The researchers conducted an experiment to answer this question. They recruited people at a science fair, giving them $40 one week to make a time-saving purchase and $40 another week (either before or after) to make a material purchase. Below is a plot of what they bought on each occasion (material left, time-saving right) and the difference in happiness they reported each time.

For more details of the study see Whillans et al.. The data from the study can be accessed here.

rcParams['figure.figsize'] = 16/2.54, 35/2.54
fig,ax=plt.subplots(num=1)



# The data file we use here is a adapted from the data from `here <https://osf.io/vr9pa/>`_
# Study 8 Field Study data.
df=pd.read_csv("../data/happy_buy.csv",sep=';')

df['DIFF_PA']=  df['TP_PA']-df['MAT_PA']
df=df.sort_values('DIFF_PA')

i=0
for di in df.iterrows():

    i=i+1
    d=di[1]
    cl='orange'

    ax.plot([0,d['TP_PA']-d['MAT_PA']],[i,i], linestyle='solid', markersize=4, marker='o', color=cl)
    if (d['TP_PA'] > d['MAT_PA']):
        ax.text(d['TP_PA']-d['MAT_PA']+0.1,i-0.25, d['TS_Purchase'] , color='black' )
        ax.text(0-0.1,i-0.25, d['MAT_Item_1'], ha='right' , color='black')
    else:
        ax.text(d['TP_PA']-d['MAT_PA']-0.1,i-0.25, d['MAT_Item_1'], ha='right' , color='black' )
        ax.text(0+0.1,i-0.25, d['TS_Purchase'] , color='black' )

ax.set_yticks([-10,100])
ax.set_ylim(0,61)
ax.set_xlim(-2,4)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.set_xlabel('Happiness difference (scale 0-5)')
plt.show()

np.sum(df['DIFF_PA']>0.2)
np.sum(df['DIFF_PA']<-0.2)
plot happyperson
np.int64(14)

Answer to fourth question: Again, there are no guarantees that eating out or getting a babysitter will make you happy, but it worked for 26 out of the 60 people participating in the study, with only 14 being happier with a material purchase.

Total running time of the script: (0 minutes 1.687 seconds)

Gallery generated by Sphinx-Gallery