circ_hktest.m 6.4 KB

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