function pout=myBinomTest(s,n,p,Sided) %function pout=myBinomTest(s,n,p,Sided) % % Performs a binomial test of the number of successes given a total number % of outcomes and a probability of success. Can be one or two-sided. % % Inputs: % s- (Scalar or Array) The observed numebr of successful outcomes % n- (Scalar or Array) The total number of outcomes (successful or not) % p- (Scalar or Array) The proposed probability of a successful outcome % Sided- (String) can be 'Two','Greater' or 'Lesser'. A value of % 'Two' will perform a two-sided test, that the actual number % of success is different from the expected number of % successes in any direction. 'Greater' or 'Lesser' will % perform a 1-sided test to examine if the observed number of % successes are either significantly greter than or less than % (respectively) the expected number of successes. % % Outputs: % pout- The probability of observing the resulting value of s or a % value more extreme (the precise meaning of which depends on % the value of Sided) given n total outcomes with a % probability of success of p. % % s, n and p can be scalars or arrays of the same size. The % dimensions and size of pout will match that of these inputs. % % For example, the signtest is a special case of this where the value of p % is equal to 0.5 (and a 'success' is dfeined by whether or not a given % sample is of a particular sign.), but the binomial test and this code is % more general allowing the value of p to be any value between 0 and 1. % % References: % http://en.wikipedia.org/wiki/Binomial_test % % by Matthew Nelson July 21st, 2009 % matthew.j.nelson.vumail@gmail.com if nargin<4 || isempty(Sided); Sided='Two'; end if nargin<3 || isempty(p); p=0.5; end switch lower(Sided) case 'two' [s,n,p]= EqArrayAndScalars(s,n,p); E=p.*n; GreaterInds=s>=E; pout=repmat(0,size(GreaterInds)); dE=pout; %note that matlab's binocdf(s,n,p) gives the prob. of getting up to AND INCLUDING s # of successes... %Calc pout for GreaterInds first pout(GreaterInds)=1-binocdf( s(GreaterInds)-1,n(GreaterInds),p(GreaterInds)); %start with the prob of getting >= s # of successes %now figure the difference from the expected value, and figure the prob of getting lower than that difference from the expected value # of successes dE(GreaterInds)=s(GreaterInds)-E(GreaterInds); pout(GreaterInds)=pout(GreaterInds)+ binocdf(floor(E(GreaterInds)-dE(GreaterInds)),n(GreaterInds),p(GreaterInds)); %the binonmial is a discrete dist. ... so it's value over non-integer args has no menaing... this flooring of E-dE actually doesn't affect the outcome (the result is teh same if the floor was removed) but it's included here as a reminder of the discrete nature of the binomial %If the expected value is exactly equaled, the above code would have added the probability at that discrete value twice, so we need to adjust (in this case, pout will always = 1 anyways) if dE==0 pout(GreaterInds)=pout(GreaterInds)- binopdf( E(GreaterInds),n(GreaterInds),p(GreaterInds) ); end %Calc pout for LesserInds second pout(~GreaterInds)=binocdf(s(~GreaterInds),n(~GreaterInds),p(~GreaterInds)); %start with the prob of getting <= s # of successes %now figure the difference from the expected value, and figure the prob of getting greater than that difference from teh expected value # of successes dE(~GreaterInds)=E(~GreaterInds)-s(~GreaterInds); pout(~GreaterInds)=pout(~GreaterInds) + 1-binocdf(ceil(E(~GreaterInds)+dE(~GreaterInds))-1,n(~GreaterInds),p(~GreaterInds)); %Here teh ceiling is needed b/c of teh -1 following it, so that integer and non-integer vals of E+dE will bothe give teh correct value with teh same line of code case 'greater' %one-sided pout=1-binocdf(s-1,n,p); %just report the prob of getting >= s # of successes case 'lesser' %one-sided pout=binocdf(s,n,p); %just report the prob of getting <= s # of successes otherwise error(['In myBinomTest, Sided variable is: ' Sided '. Unkown sided value.']) end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function varargout=EqArrayAndScalars(varargin) %function varargout=EqArrayAndScalars(varargin) % % This will compare a collection of inputs that must be either scalars or % arrays of the same size. If there is at least one array input, all scalar % inputs will be replicated to be the array of that same size. If there are % two or more array inputs that have different sizes, this will return an % error. % % created by Matthew Nelson on April 13th, 2010 % matthew.j.nelson.vumail@gmail.com d=repmat(0,nargin,1); for ia=1:nargin d(ia)=ndims(varargin{ia}); end maxnd=max(d); s=repmat(1,nargin,maxnd); for ia=1:nargin s(ia,1:d(ia))=size(varargin{ia}); end maxs=max(s); for ia=1:nargin if ~all(s(ia,:)==maxs) if ~all(s(ia,:)==1) error(['Varargin{' num2str(ia) '} needs to be a scalar or equal to the array size of other array inputs.']) else varargout{ia}=repmat(varargin{ia},maxs); end else varargout{ia}=varargin{ia}; end end