[banner]

A Python Companion to Extension Program Evaluation

Salvatore S. Mangiafico

Mood’s Median Test

Mood’s median test in SAEPER

 

For a discussion of this test, see the corresponding chapter in Summary and Analysis of Extension Program Evaluation in R (rcompanion.org/handbook/F_09.html).

 

Importing packages in this chapter

 

The following commands will import required packages used in this chapter from libraries and assign them common aliases.  You may need install these libraries first.

 

import io

 

import os

 

import numpy as np

 

import scipy.stats as stats

 

import pandas as pd

 

import matplotlib.pyplot as plt

 

import pingouin as pg

 

import seaborn as sns

 

import math

 

 

Setting your working directory

 

You may wish to set your working directory for exported plots.

 

os.chdir("C:/Users/Sal Mangiafico/Desktop")

 

print(os.getcwd())

 

 

Example of Mood’s median test

 

Data = pd.read_table(sep="\\s+", filepath_or_buffer=io.StringIO("""
 Speaker  Likert

 Pooh      3

 Pooh      5

 Pooh      4

 Pooh      4

 Pooh      4

 Pooh      4

 Pooh      4

 Pooh      4

 Pooh      5

 Pooh      5

 Piglet    2

 Piglet    4

 Piglet    2

 Piglet    2

 Piglet    1

 Piglet    2

 Piglet    3

 Piglet    2

 Piglet    2

 Piglet    3

 Tigger    4

 Tigger    4

 Tigger    4

 Tigger    4

 Tigger    5

 Tigger    3

 Tigger    5

 Tigger    4

 Tigger    4

 Tigger    3
"""))



Summarize data treating Likert scores as numeric

 

Summary = Data.groupby('Speaker')['Likert'].describe()

 

print(Summary)

 

          count  mean       std  min  25%  50%   75%  max

Speaker                                                

Piglet    10.0   2.3  0.823273  1.0  2.0  2.0  2.75  4.0

Pooh      10.0   4.2  0.632456  3.0  4.0  4.0  4.75  5.0

Tigger    10.0   4.0  0.666667  3.0  4.0  4.0  4.00  5.0

 

### The 50% percentile is the median for each group

 

 

Mood’s median test

 

Using scipy.stats

 

Pooh = Data['Likert'][Data['Speaker']=='Pooh']

 

Piglet = Data['Likert'][Data['Speaker']=='Piglet']

 

Tigger = Data['Likert'][Data['Speaker']=='Tigger']

 

stats.median_test(Piglet, Pooh, Tigger)

 

MedianTestResult(statistic=3.3599999999999994, pvalue=0.18637397603940997, median=4.0)

 

 

As mentioned in the SAEPER chapter, we’ll invert the scale on the Likert item responses.  This is related to so many responses being equal to the global median, 4.

 

Data['Likert.inv'] = 6 - Data['Likert']

 

 

Pooh = Data['Likert.inv'][Data['Speaker']=='Pooh']

 

Piglet = Data['Likert.inv'][Data['Speaker']=='Piglet']

 

Tigger = Data['Likert.inv'][Data['Speaker']=='Tigger']

 

 

stats.median_test(Piglet, Pooh, Tigger)

 

MedianTestResult(statistic=15.833333333333334, pvalue=0.0003646156887302732, median=2.0)

 

### Note: This is based on the inverted responses

 

 

Effect size measurements

 

Appropriate effect size statistics may include those for the two-sample case, applied on each pair of groups.

 

 

Manual calculation of Mood’s median test

 

medianOverall = Data['Likert.inv'].median()

 

medianOverall

 

2.0

 

### Note: This is the median of the inverted responses

 

 

PoohHigher = sum(Data['Likert.inv'][Data['Speaker']=='Pooh'] > medianOverall)

 

PigletHigher = sum(Data['Likert.inv'][Data['Speaker']=='Piglet'] > medianOverall)

 

TiggerHigher =sum(Data['Likert.inv'][Data['Speaker']=='Tigger'] > medianOverall)

 

PoohLower = sum(Data['Likert.inv'][Data['Speaker']=='Pooh'] <= medianOverall)

 

PigletLower = sum(Data['Likert.inv'][Data['Speaker']=='Piglet'] <= medianOverall)

 

TiggerLower = sum(Data['Likert.inv'][Data['Speaker']=='Tigger'] <= medianOverall)

 

 

Matrix = np.array([[PoohHigher, PoohLower], [PigletHigher, PigletLower],

                   [TiggerHigher, TiggerLower]])

 

 

So the following the contingency table would be used by Mood’s median test.

 

       GreaterThanEqualMu.inv  LessThanMu.inv

Pooh                    1          9

Piglet                  9          1

Tigger                  2          8

 

 

stats.chi2_contingency(Matrix)

 

Chi2ContingencyResult(statistic=15.833333333333334, pvalue=0.0003646156887302732, dof=2)

 

### Note this is the same as the output from Pingouin above