Mood’s median test compares the medians of two or more groups. It is often less powerful than the Kruskal–Wallis test, but specifically tests for a difference in medians.

The test can be conducted with the *mood.medtest*
function in the *RVAideMemoire* package or with the *median_test* function
in the *coin* package.

##### Post-hoc tests

The outcome of Mood’s median test tells you if there are
differences among the groups, but doesn’t tell you *which* groups are
different from other groups. In order to determine which groups are different
from others, post-hoc testing can be conducted. The function *pairwiseMedianTest*
in the *rcompanion* package can perform the post-hoc tests.

##### Appropriate data

• One-way data with two or more groups

• Dependent variable is ordinal, interval, or ratio

• Independent variable is a factor with levels indicating groups

• Observations between groups are independent. That is, not paired or repeated measures data

##### Hypotheses

• Null hypothesis: The medians of values for each group are equal.

• Alternative hypothesis (two-sided): The medians of values for each group are not equal.

##### Interpretation

Significant results can be reported as “There was a significant difference in the median values among groups.”

Post-hoc analysis allows you to say “The median for group A was higher than the median for group B”, and so on.

### Packages used in this chapter

The packages used in this chapter include:

• RVAideMemoire

• coin

• rcompanion

The following commands will install these packages if they are not already installed:

if(!require(RVAideMemoire)){install.packages("RVAideMemoire")}

if(!require(coin)){install.packages("coin")}

if(!require(rcompanion)){install.packages("rcompanion")}

### Example using the *RVAideMemoire* package

This example uses the formula notation indicating that *Likert*
is the dependent variable and *Speaker* is the independent variable. The *data=*
option indicates the data frame that contains the variables. For the meaning
of other options, see *?mood.medtest*.

A significant *p*-value for Mood’s median test
indicates that not all medians among groups are equal.

For appropriate plots and data frame checking, see the *Kruskal–Wallis
Test* chapter.

Input =("

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

")

Data = read.table(textConnection(Input),header=TRUE)

### Check the data frame

library(psych)

headTail(Data)

str(Data)

summary(Data)

### Remove unnecessary objects

rm(Input)

#### Mood’s median test

library(RVAideMemoire)

mood.medtest(Likert ~ Speaker,

data = Data,

exact = FALSE)

Mood's median test

X-squared = 3.36, df = 2, p-value = 0.1864

An interesting thing happened with the result here. The
test counts how many observations in each group are greater than the global
median for all groups together, in this case 4. It then tests if there is a
significant difference in this proportion among groups. For this data set,
however, both Pooh and Tigger have a majority of observations equal to the
global median. Because they are *equal* to the global median, they are
not *greater than* the global median, and so aren’t much different than
Piglet’s scores on this count. The result in this case is a non-significant *p*-value.

But the test would come out differently if we were counting
observation *less than* the global median, because Pooh and Tigger have
few of these, and Piglet has relatively many.

This is a quirk with Mood’s median test, and isn’t common in statistical tests.

One solution would be to re-code the function to count observations less than the global median. This would be possible.

But it is easier to simply invert the scale we are using. This is really an arbitrary change, but for this test, it can make a difference. Imagine if our original scale interpreted 5 to be the best, and 1 to be the worst. When we designed the survey tool, we could just as easily have made 1 the best and 5 the worst. And then instead of ranking “good” with a 4, the respondents would have marked it 2, and so on. By the way the calculations are done, this arbitrary change in scale will change the results of Mood’s median test.

For a 5-point scale, we do this inversion by simply by making a new variable equal to 6 minus the original score.

With Mood’s median test, I recommend making this kind of
inversion in cases where many values are equal to the global median. Then use
whichever result has a lower *p*-value.

Data$Likert.inv = 6 - Data$Likert

library(psych)

headTail(Data)

Speaker Likert Likert.inv

1 Pooh 3 3

2 Pooh 5 1

3 Pooh 4 2

4 Pooh 4 2

... <NA> ... ...

27 Tigger 5 1

28 Tigger 4 2

29 Tigger 4 2

30 Tigger 3 3

library(RVAideMemoire)

mood.medtest(Likert.inv ~ Speaker,

data = Data,

exact = FALSE)

Mood's median test

X-squared
= 15.833, df = 2, p-value = 0.0003646

Approximative K-Sample Brown-Mood Median Test

chi-squared = 15.306, p-value = 1e-04

#### Post-hoc test: pairwiseMedianTest function

If Mood’s median test is significant, a post-hoc analysis can be performed to determine which groups differ from each other group.

For this we will use the *pairwiseMedianTest* function
in the *rcompanion* package, which conducts Mood’s median test on all
pairs of groups from one-way data.

Because the post-hoc test will produce multiple *p*-values,
adjustments to the *p*-values can be made to avoid inflating the
possibility of making a type-I error. There are a variety of methods for
controlling the familywise error rate or for controlling the false discovery
rate. See *?p.adjust* for details on these methods.

### Order groups by median

Data$Speaker = factor(Data$Speaker,

levels=c("Pooh", "Tigger",
"Piglet"))

### Pairwise median tests

library(rcompanion)

PT = pairwiseMedianTest(Likert
~ Speaker,

data = Data,

exact = NULL,

method = "fdr")

#
Adjusts p-values for multiple comparisons;

# See ?p.adjust for
options

PT

Comparison p.value p.adjust

1 Pooh - Tigger = 0 1 1.000000

2 Pooh - Piglet = 0 0.001093 0.003279

3 Tigger - Piglet = 0 0.005477 0.008216

### Compact letter display

library(rcompanion)

cldList(p.adjust ~ Comparison,

data = PT,

threshold = 0.05)

Group Letter MonoLetter

1 Pooh a a

2 Tigger a a

3 Piglet b b

Groups sharing a letter are not significantly
different (alpha = 0.05).

#### Post-hoc test: pairwiseMedianMatrix function

### Order groups by median

Data$Speaker = factor(Data$Speaker,

levels=c("Pooh", "Tigger",
"Piglet"))

### Pairwise median tests

library(rcompanion)

PT = pairwiseMedianMatrix(Likert
~ Speaker,

data = Data,

exact = NULL,

method = "fdr")

#
Adjusts p-values for multiple comparisons;

# See ?p.adjust for
options

PT

library(multcompView)

multcompLetters(PT$Adjusted,

compare="<",

threshold=0.05,

Letters=letters)

Pooh Tigger Piglet

"a" "a" "b"