-
Notifications
You must be signed in to change notification settings - Fork 41
/
circ_hktest.m
241 lines (190 loc) · 6.43 KB
/
circ_hktest.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
function [pval, table] = circ_hktest(alpha, idp, idq, inter, fn)
%
% [pval, stats] = circ_hktest(alpha, idp, idq, inter, fn)
% Parametric two-way ANOVA for circular data with interations.
%
% Input:
% alpha angles in radians
% idp indicates the level of factor 1 (1:p)
% idq indicates the level of factor 2 (1:q)
% inter 0 or 1 - whether to include effect of interaction or not
% fn cell array containing strings with the names of the factors
%
%
% Output:
% pval vector of pvalues testing column, row and interaction effects
% table cell array containg the anova table
%
% The test assumes underlying von-Mises distributrions.
% All groups are assumed to have a common concentration parameter k,
% between 0 and 2.
%
% Update 2012
% PHB 7/19/2009 with code by Tal Krasovsky, Mc Gill University
%
% References:
% Harrison, D. and Kanji, G. K. (1988). The development of analysis of variance for
% circular data. Journal of applied statistics, 15(2), 197-223.
%
% Circular Statistics Toolbox for Matlab
% process inputs
alpha = alpha(:); idp = idp(:); idq = idq(:);
if nargin < 4
inter = true;
end
if nargin < 5
fn = {'A','B'};
end
% number of groups for every factor
pu = unique(idp);
p = length(pu);
qu = unique(idq);
q = length(qu);
% number of samples
n = length(alpha);
% compute important sums for the test statistics
cn = zeros(p,q); cr = cn;
pm = zeros(p,1); pr = pm; pn = pm;
qm = zeros(q,1); qr = qm; qn = qm;
for pp = 1:p
p_id = idp == pu(pp); % indices of factor1 = pp
for qq = 1:q
q_id = idq == qu(qq); % indices of factor2 = qq
idx = p_id & q_id;
cn(pp,qq) = sum(idx); % number of items in cell
cr(pp,qq) = cn(pp,qq) * circ_r(alpha(idx)); % R of cell
end
% R and mean angle for factor 1
pr(pp) = sum(p_id) * circ_r(alpha(p_id));
pm(pp) = circ_mean(alpha(p_id));
pn(pp) = sum(p_id);
end
% R and mean angle for factor 2
for qq = 1:q
q_id = idq == qu(qq);
qr(qq) = sum(q_id) * circ_r(alpha(q_id));
qm(qq) = circ_mean(alpha(q_id));
qn(qq) = sum(q_id);
end
% R and mean angle for whole sample (total)
tr = n * circ_r(alpha);
% estimate kappa
kk = circ_kappa(tr/n);
% different formulas for different width of the distribution
if kk > 2
% large kappa
% effect of factor 1
eff_1 = sum(pr.^2 ./ sum(cn,2)) - tr.^2/n;
df_1 = p-1;
ms_1 = eff_1 / df_1;
% effect of factor 2
eff_2 = sum(qr.^2 ./ sum(cn,1)') - tr.^2/n;
df_2 = q-1;
ms_2 = eff_2 / df_2;
% total effect
eff_t = n - tr.^2/n;
df_t = n-1;
m = mean(cn(:));
if inter
% correction factor for improved F statistic
beta = 1/(1-1/(5*kk)-1/(10*(kk^2)));
% residual effects
eff_r = n - sum(sum(cr.^2./cn));
df_r = p*q*(m-1);
ms_r = eff_r / df_r;
% interaction effects
eff_i = sum(sum(cr.^2./cn)) - sum(qr.^2./qn) ...
- sum(pr.^2./pn) + tr.^2/n;
df_i = (p-1)*(q-1);
ms_i = eff_i/df_i;
% interaction test statistic
FI = ms_i / ms_r;
pI = 1-fcdf(FI,df_i,df_r);
else
% residual effect
eff_r = n - sum(qr.^2./qn)- sum(pr.^2./pn) + tr.^2/n;
df_r = (p-1)*(q-1);
ms_r = eff_r / df_r;
% interaction effects
eff_i = [];
df_i = [];
ms_i =[];
% interaction test statistic
FI = [];
pI = NaN;
beta = 1;
end
% compute all test statistics as
% F = beta * MS(A) / MS(R);
F1 = beta * ms_1 / ms_r;
p1 = 1 - fcdf(F1,df_1,df_r);
F2 = beta * ms_2 / ms_r;
p2 = 1 - fcdf(F2,df_2,df_r);
else
% small kappa
% correction factor
rr = besseli(1,kk) / besseli(0,kk);
f = 2/(1-rr^2);
chi1 = f * (sum(pr.^2./pn)- tr.^2/n);
df_1 = 2*(p-1);
p1 = 1 - chi2cdf(chi1, df_1);
chi2 = f * (sum(qr.^2./qn)- tr.^2/n);
df_2 = 2*(q-1);
p2 = 1 - chi2cdf(chi2, df_2);
chiI = f * (sum(sum(cr.^2 ./ cn)) - sum(pr.^2./pn) ...
- sum(qr.^2./qn)+ tr.^2/n);
df_i = (p-1) * (q-1);
% pI = 1 - chi2pdf(chiI, df_i); % bugfix 2012
pI = 1 - chi2cdf(chiI, df_i);
end
na = nargout;
if na < 2
printTable;
end
prepareOutput;
function printTable
if kk>2
fprintf('\nANALYSIS OF VARIANCE TABLE (HIGH KAPPA MODE)\n\n');
fprintf('%s\t\t\t\t%s\t%s\t\t%s\t\t%s\t\t\t%s\n', ' ' ,'d.f.', 'SS', 'MS', 'F', 'P-Value');
fprintf('--------------------------------------------------------------------\n');
fprintf('%s\t\t\t\t%u\t\t%.2f\t%.2f\t%.2f\t\t%.4f\n', fn{1}, df_1 , eff_1, ms_1, F1, p1);
fprintf('%s\t\t\t\t%u\t\t%.2f\t%.2f\t%.2f\t\t%.4f\n', fn{2}, df_2 , eff_2, ms_2, F2, p2);
if (inter)
fprintf('%s\t\t%u\t\t%.2f\t%.2f\t%.2f\t\t%.4f\n', 'Interaction', df_i , eff_i, ms_i, FI, pI);
end
fprintf('%s\t\t%u\t\t%.2f\t%.2f\n', 'Residual ', df_r, eff_r, ms_r);
fprintf('--------------------------------------------------------------------\n');
fprintf('%s\t\t%u\t\t%.2f', 'Total ',df_t,eff_t);
fprintf('\n\n')
else
fprintf('\nANALYSIS OF VARIANCE TABLE (LOW KAPPA MODE)\n\n');
fprintf('%s\t\t\t\t%s\t%s\t\t\t%s\n', ' ' ,'d.f.', 'CHI2', 'P-Value');
fprintf('--------------------------------------------------------------------\n');
fprintf('%s\t\t\t\t%u\t\t%.2f\t\t\t%.4f\n', fn{1}, df_1 , chi1, p1);
fprintf('%s\t\t\t\t%u\t\t%.2f\t\t\t%.4f\n', fn{2}, df_2 , chi2, p2);
if (inter)
fprintf('%s\t\t%u\t\t%.2f\t\t\t%.4f\n', 'Interaction', df_i , chiI, pI);
end
fprintf('--------------------------------------------------------------------\n');
fprintf('\n\n')
end
end
function prepareOutput
pval = [p1 p2 pI];
if na > 1
if kk>2
table = {'Source','d.f.','SS','MS','F','P-Value'; ...
fn{1}, df_1 , eff_1, ms_1, F1, p1; ...
fn{2}, df_2 , eff_2, ms_2, F2, p2; ...
'Interaction', df_i , eff_i, ms_i, FI, pI; ...
'Residual', df_r, eff_r, ms_r, [], []; ...
'Total',df_t,eff_t,[],[],[]};
else
table = {'Source','d.f.','CHI2','P-Value'; ...
fn{1}, df_1 , chi1, p1;
fn{2}, df_2 , chi2, p2;
'Interaction', df_i , chiI, pI};
end
end
end
end