Quade 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_11.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 pingouin as pg
import scikit_posthocs as sp
import matplotlib.pyplot as plt
import seaborn as sns
from statds.no_parametrics import quade
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 Quade test
Data = pd.read_table(sep="\\s+", filepath_or_buffer=io.StringIO("""
Instructor Rater Likert
"Bob Belcher" a 4
"Bob Belcher" b 5
"Bob Belcher" c 4
"Bob Belcher" d 6
"Bob Belcher" e 6
"Bob Belcher" f 6
"Bob Belcher" g 10
"Bob Belcher" h 6
"Linda Belcher" a 8
"Linda Belcher" b 6
"Linda Belcher" c 8
"Linda Belcher" d 8
"Linda Belcher" e 8
"Linda Belcher" f 7
"Linda Belcher" g 10
"Linda Belcher" h 9
"Tina Belcher" a 7
"Tina Belcher" b 5
"Tina Belcher" c 7
"Tina Belcher" d 8
"Tina Belcher" e 8
"Tina Belcher" f 9
"Tina Belcher" g 10
"Tina Belcher" h 9
"Gene Belcher" a 6
"Gene Belcher" b 4
"Gene Belcher" c 5
"Gene Belcher" d 5
"Gene Belcher" e 6
"Gene Belcher" f 6
"Gene Belcher" g 5
"Gene Belcher" h 5
"Louise Belcher" a 8
"Louise Belcher" b 7
"Louise Belcher" c 8
"Louise Belcher" d 8
"Louise Belcher" e 9
"Louise Belcher" f 9
"Louise Belcher" g 8
"Louise Belcher" h 10
"""))
### Convert Instructor and Rater to category type
Data['Instructor'] = Data['Instructor'].astype('category')
Data['Rater'] = Data['Rater'].astype('category')
### Create new variable, Likert as a category variable
Data['Likert.f'] = Data['Likert'].astype('category')
### Order Speaker by desired values
InstructorLevels = ['Bob Belcher', 'Linda Belcher', 'Tina Belcher',
'Gene Belcher', 'Louise Belcher']
Data['Instructor'] = Data['Instructor'].cat.reorder_categories(InstructorLevels)
print(Data['Instructor'].cat.categories)
Index(['Bob Belcher', 'Linda Belcher', 'Tina Belcher', 'Gene Belcher',
'Louise Belcher'],
dtype='object')
print(Data.info())
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Instructor 40 non-null category
1 Rater 40 non-null category
2 Likert 40 non-null int64
3 Likert.f 40 non-null category
Summarize data treating Likert scores as categories
pd.crosstab(Data['Instructor'], Data['Likert.f'])
Likert.f 4 5 6 7 8 9 10
Instructor
Bob Belcher 2 1 4 0 0 0 1
Linda Belcher 0 0 1 1 4 1 1
Tina Belcher 0 1 0 2 2 2 1
Gene Belcher 1 4 3 0 0 0 0
Louise Belcher 0 0 0 1 4 2 1
pd.crosstab(Data['Instructor'], Data['Likert.f'], normalize='index')
Likert.f 4 5 6 7 8 9 10
Instructor
Bob Belcher 0.250 0.125 0.500 0.000 0.00 0.000 0.125
Linda Belcher 0.000 0.000 0.125 0.125 0.50 0.125 0.125
Tina Belcher 0.000 0.125 0.000 0.250 0.25 0.250 0.125
Gene Belcher 0.125 0.500 0.375 0.000 0.00 0.000 0.000
Louise Belcher 0.000 0.000 0.000 0.125 0.50 0.250 0.125
Bar plots of data by group
sns.set_theme(style='white')
Plot = sns.FacetGrid(data=Data, row='Instructor',
margin_titles=True, height=2, aspect= 2)
Plot.map(sns.countplot, 'Likert.f')
Plot.tight_layout()
Plot.savefig('LikertBarBelcher.png', format='png', dpi=300)

Summarize data treating Likert scores as numeric
Summary = Data.groupby('Instructor')['Likert'].describe()
print(Summary)
count mean std min 25% 50% 75% max
Instructor
Bob Belcher 8.0 5.875 1.885092 4.0 4.75 6.0 6.00 10.0
Linda Belcher 8.0 8.000 1.195229 6.0 7.75 8.0 8.25 10.0
Tina Belcher 8.0 7.875 1.552648 5.0 7.00 8.0 9.00 10.0
Gene Belcher 8.0 5.250 0.707107 4.0 5.00 5.0 6.00 6.0
Louise Belcher 8.0 8.375 0.916125 7.0 8.00 8.0 9.00 10.0
Quade test example
Using StaTDS
The quade() function in StaTDS expects data in wide format. We’ll create a new data frame, Data1, with the first column as the block and the remaining columns having observations for each of the groups or treatments.
Rater = np.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Bob = np.array(Data['Likert'][Data['Instructor'] == 'Bob Belcher'])
Linda = np.array(Data['Likert'][Data['Instructor'] == 'Linda Belcher'])
Tina = np.array(Data['Likert'][Data['Instructor'] == 'Tina Belcher'])
Gene = np.array(Data['Likert'][Data['Instructor'] == 'Gene Belcher'])
Louise = np.array(Data['Likert'][Data['Instructor'] == 'Louise Belcher'])
Data1 = pd.DataFrame({'Rater': Rater, 'Bob': Bob, 'Linda': Linda, 'Tina': Tina, 'Gene': Gene, 'Louise': Louise})
Data1
Rater Bob Linda Tina Gene Louise
0 a 4 8 7 6 8
1 b 5 6 5 4 7
2 c 4 8 7 5 8
3 d 6 8 8 5 8
4 e 6 8 8 6 9
5 f 6 7 9 6 9
6 g 10 10 10 5 8
7 h 6 9 9 5 10
quade(Data1)
({'Bob': 3.923611111111111,
'Linda': 2.0555555555555554,
'Tina': 2.513888888888889,
'Gene': 4.625,
'Louise': 1.8819444444444444},
8.025290473231268,
0.00019236606572845994
### The output lists the average ranks for each group,
### and the test statistic and the p-value.
rankings, statistic, p_value, critical_value, hypothesis = quade(Data1)
round(statistic, 4)
8.0253
round(p_value, 6)
0.000192
Post-hoc test for multiple comparisons of groups
Results below differ from those reported by R. This has to do with differences p-value adjustment methods.
The following call will prevent pandas from truncating the output.
pd.set_option('display.max_columns', 500)
The following will order the Instructor categories by their median responses. It appears, though, that this ordering isn’t used in the following post-hoc functions.
InstructorLevels = ['Linda Belcher', 'Louise Belcher','Tina Belcher',
'Bob Belcher','Gene Belcher']
Data['Instructor'] = Data['Instructor'].cat.reorder_categories(InstructorLevels)
print(Data['Instructor'].cat.categories)
Index(['Linda Belcher', 'Louise Belcher', 'Tina Belcher', 'Bob Belcher',
'Gene Belcher'],
dtype='object')
Quade post-hoc test
Several different p-value adjustment methods are available. See the function documentation for the options.
sp.posthoc_quade(Data, melted=True,
y_col='Likert', group_col='Instructor',
block_col='Rater', block_id_col='Rater',
p_adjust=None)
Bob Belcher Linda Belcher Tina Belcher Gene Belcher Louise Belcher
Bob Belcher 1.000000 0.004508 0.027198 0.256002 0.002176
Linda Belcher 0.004508 1.000000 0.454923 0.000215 0.776202
Tina Belcher 0.027198 0.454923 1.000000 0.001617 0.305055
Gene Belcher 0.256002 0.000215 0.001617 1.000000 0.000099
Louise Belcher 0.002176 0.776202 0.305055 0.000099 1.000000
Example from Conover
This example is taken from the Quade test section of Conover (1999).
Conover = pd.read_table(sep="\\s+", filepath_or_buffer=io.StringIO("""
Store A B C D E
1 5 4 7 10 12
2 1 3 1 0 2
3 16 12 22 22 35
4 5 4 3 5 4
5 10 9 7 13 10
6 19 18 28 37 58
7 10 7 6 8 7
"""))
quade(Conover)
({'A': 3.3392857142857144,
'B': 4.357142857142857,
'C': 3.5,
'D': 2.1607142857142856,
'E': 1.6428571428571428},
3.8292515841753727,
0.015189020073274623
rankings, statistic, p_value, critical_value, hypothesis = quade(Conover)
round(statistic, 4)
3.8293
round(p_value, 5)
0.01519
Post-hoc test
Results below differ from those reported by R. This has to do with differences p-value adjustment methods.
pd.set_option('display.max_columns', 500)
Quade post-hoc test
Several different p-value adjustment methods are available. See the function documentation for the options.
sp.posthoc_quade(Conover, p_adjust=None)
Store A B C D E
Store 1.000000 0.028715 0.255619 0.059560 0.001082 0.000248
A 0.028715 1.000000 0.263730 0.736455 0.197214 0.072962
B 0.255619 0.263730 1.000000 0.430414 0.019976 0.005427
C 0.059560 0.736455 0.430414 1.000000 0.107638 0.035804
D 0.001082 0.197214 0.019976 0.107638 1.000000 0.593516
E 0.000248 0.072962 0.005427 0.035804
0.593516 1.000000
References
Conover, W.J. 1999. Practical Nonparametric Statistics, 3rd. John Wiley & Sons.
Luna, C., A.R. Moya, J.M. Luna, S. Ventura . 2024. StaTDS library: Statistical tests for Data Science. Neurocomputing 595:127877. doi.org/10.1016/j.neucom.2024.127877.
StaTDS: Library for statistical testing and comparison of algorithm results. github.com/kdis-lab/StaTDS.
Statistical Tests for Data Science (StaTDS). statds.readthedocs.io/en/latest/.