-
Notifications
You must be signed in to change notification settings - Fork 41
/
circ_wwtest.m
162 lines (138 loc) · 4.8 KB
/
circ_wwtest.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
function [pval, table] = circ_wwtest(varargin)
%
% [pval, table] = circ_wwtest(alpha, idx, [w])
% [pval, table] = circ_wwtest(alpha1, alpha2, [w1, w2])
% Parametric Watson-Williams multi-sample test for equal means. Can be
% used as a one-way ANOVA test for circular data.
%
% H0: the s populations have equal means
% HA: the s populations have unequal means
%
% Note:
% Use with binned data is only advisable if binning is finer than 10 deg.
% In this case, alpha is assumed to correspond
% to bin centers.
%
% The Watson-Williams two-sample test assumes underlying von-Mises
% distributrions. All groups are assumed to have a common concentration
% parameter k.
%
% Input:
% alpha angles in radians
% idx indicates which population the respective angle in alpha
% comes from, 1:s
% [w number of incidences in case of binned angle data]
%
% Output:
% pval p-value of the Watson-Williams multi-sample test. Discard H0 if
% pval is small.
% table cell array containg the ANOVA table
%
% PHB 3/19/2009
%
% References:
% Biostatistical Analysis, J. H. Zar
%
% Circular Statistics Toolbox for Matlab
% Update 2012
% By Philipp Berens, 2009
% [email protected] - www.kyb.mpg.de/~berens/circStat.html
[alpha, idx, w] = processInput(varargin{:});
% number of groups
u = unique(idx);
s = length(u);
% number of samples
n = sum(w);
% compute relevant quantitites
pn = zeros(s,1); pr = pn;
for t=1:s
pidx = idx == u(t);
pn(t) = sum(pidx.*w);
pr(t) = circ_r(alpha(pidx),w(pidx));
end
r = circ_r(alpha,w);
rw = sum(pn.*pr)/n;
% make sure assumptions are satisfied
checkAssumption(rw,mean(pn))
% test statistic
kk = circ_kappa(rw);
beta = 1+3/(8*kk); % correction factor
A = sum(pr.*pn) - r*n;
B = n - sum(pr.*pn);
F = beta * (n-s) * A / (s-1) / B;
pval = 1 - fcdf(F,s-1,n-s);
na = nargout;
if na < 2
printTable;
end
prepareOutput;
function printTable
fprintf('\nANALYSIS OF VARIANCE TABLE (WATSON-WILLIAMS TEST)\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%u\t\t%.2f\t%.2f\t%.2f\t\t%.4f\n', 'Columns', s-1 , A, A/(s-1), F, pval);
fprintf('%s\t\t%u\t\t%.2f\t%.2f\n', 'Residual ', n-s, B, B/(n-s));
fprintf('--------------------------------------------------------------------\n');
fprintf('%s\t\t%u\t\t%.2f', 'Total ',n-1,A+B);
fprintf('\n\n')
end
function prepareOutput
if na > 1
table = {'Source','d.f.','SS','MS','F','P-Value'; ...
'Columns', s-1 , A, A/(s-1), F, pval; ...
'Residual ', n-s, B, B/(n-s), [], []; ...
'Total',n-1,A+B,[],[],[]};
end
end
end
function checkAssumption(rw,n)
if n >= 11 && rw<.45
warning('CIRCSTAT:circ_wwtest:vectorTooShort', ...
'Test not applicable. Average resultant vector length < 0.45.') %#ok<WNTAG>
elseif n<11 && n>=7 && rw<.5
warning('CIRCSTAT:circ_wwtest:sampleSize6x11AndVectorTooShort', ...
'Test not applicable. Average number of samples per population 6 < x < 11 and average resultant vector length < 0.5.') %#ok<WNTAG>
elseif n>=5 && n<7 && rw<.55
warning('CIRCSTAT:circ_wwtest:sampleSize4x7AndVectorTooShort', ...
'Test not applicable. Average number of samples per population 4 < x < 7 and average resultant vector length < 0.55.') %#ok<WNTAG>
elseif n < 5
warning('CIRCSTAT:circ_wwtest:sampleSizeTooSmall', ...
'Test not applicable. Average number of samples per population < 5.') %#ok<WNTAG>
end
end
function [alpha, idx, w] = processInput(varargin)
if nargin == 4
alpha1 = varargin{1}(:);
alpha2 = varargin{2}(:);
w1 = varargin{3}(:);
w2 = varargin{4}(:);
alpha = [alpha1; alpha2];
idx = [ones(size(alpha1)); ones(size(alpha2))];
w = [w1; w2];
elseif nargin==2 && sum(abs(round(varargin{2})-varargin{2}))>1e-5
alpha1 = varargin{1}(:);
alpha2 = varargin{2}(:);
alpha = [alpha1; alpha2];
idx = [ones(size(alpha1)); 2*ones(size(alpha2))];
w = ones(size(alpha));
elseif nargin==2
alpha = varargin{1}(:);
idx = varargin{2}(:);
if ~(size(idx,1)==size(alpha,1))
error('Input dimensions do not match.')
end
w = ones(size(alpha));
elseif nargin==3
alpha = varargin{1}(:);
idx = varargin{2}(:);
w = varargin{3}(:);
if ~(size(idx,1)==size(alpha,1))
error('Input dimensions do not match.')
end
if ~(size(w,1)==size(alpha,1))
error('Input dimensions do not match.')
end
else
error('Invalid use of circ_wwtest. Type help circ_wwtest.')
end
end