Table of contents.

Introduction.
Which browsers?
Symmetry around zero.
The rankAbs function.
A two-sample test.
     A null hypothesis for two-sample.
     A different null hypothesis for two-sample.
Trend.
Run a JavaScript program.
The “Insert commas” button.
License, revision date, and e-mail address.

Introduction.

The program of this page is suggested by Sir Ronald Fisher’s book, The Design of Experiments, Hafner Pub. Co., New York, 1966. Any mistakes in the program are mine, not Fisher’s. The test is exact.

In the following paragraphs are some examples showing use of the program. The user is respectfully invited to try out these examples or to use any others. The only thing to remember is: follow the grammatical rules of JavaScript. (This is because the “eval” method of JavaScript is used in picking up the data from the text area.) Also, the user is respectfully reminded that integers beginning with a zero digit will be understood to be in base eight. To top.

Which browsers?

Modern browsers such as Safari 3, Microsoft Internet Explorer 6, Netscape 7, and Opera 8 can work this page correctly. Netscape 4 is out of date and cannot work this page correctly. To top.

Symmetry around zero.

The following array is for Darwin’s experiment using matched pairs of plants to compare self-fertilized and cross-fertilized.
[ 49, -67, 8, 16, 6, 23, 28, 41, 14, 29, 56, 24, 75, 60, -48 ]
Each number is a difference: cross minus self. Fisher explained that by null hypothesis these differences are distributed symmetrically around zero. The user is respectfully invited to select and copy the array, click on the “Clear” button to clear the upper text area, paste the array into that text area, and click on the “Test for symmetry around zero” button. The answers will appear in the lower text area. Doubtless the user already knows what a “p value” is. For an explanation and example of “normalized negated log p” in Bayesian meta-analysis, I respectfully invite the user to click on martMean.htm#Discrete.

The “harmonic” is the harmonic mean of the left p-value and the right p-value. It is too small to be a frequentist p-value, but its normalized negated logarithm works correctly in Bayesian meta-analysis.

Fisher’s test for Darwin’s data is non-parametric, and all it does is use convolution. There are no assumptions of normality, no ranking. However, the numbers in the array must be integers. The program is speedy for Darwin’s data, because his data have only one or two digits to each number and only 15 numbers in the array. For data with many digits to each number and 15 numbers, the required time can be several seconds. For more many-digit numbers the time can be prohibitive. For only one or two digits to each number the user can have many more numbers in the array. To top.

The rankAbs function.

It is a bit tedious not being allowed to use nonintegers in the array. Also, Fisher’s algorithm takes a long time to run. Furthermore, big outliers in the array can bring down the power. Wilcoxon’s signed ranks test is designed to overcome these three difficulties. The user need not do the ranking by human effort, because I furnish a function to do it. It is called “rankAbs.” It can handle ties correctly, just as the Fisher algorithm can. Here is how to use it on Darwin’s sample:
rankAbs( [ 49, -67, 8, 16, 6, 23, 28, 41, 14, 29, 56, 24, 75, 60, -48 ] )
As before, the user is respectfully invited to select and copy that line, click on the “Clear” button to clear the upper text area, paste the line into that text area, and click on the “Test for symmetry around zero” button. The p-values are slightly different, and so are the times.

Here is a fictitious example shown here without the rankAbs function:

         [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, -4096 ]
and with the rankAbs function:
rankAbs( [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, -4096 ] )
The p-values are entirely different, and so are the times.

Now let’s have some fractions and ties:

rankAbs( [ 0.3, 1/9, 3.3, 3.3, -3.3, 48.909, 4.89, .0321, 22/7 ] )
The user is respectfully invited. To top.

A two-sample test.

Darwin’s experiment, as Fisher pointed out, was a blocks and treatments design with 15 blocks and 2 treatments, where matching was done before treatment. The blocks and treatments null hypothesis asserted that the two treatments were really the same treatment, under different names. It is an odd thing that the same computer program can be used also for a certain kind of 2-sample test, using matching after treatment, so to speak.
A null hypothesis for two-sample.

Let the null hypothesis assert that if we take a value at random from the first population and a value at random from the second population, then the probability that the second is greater than the first is 1/2, and the probability that the second is less than the first is 1/2, and ties cannot occur. This is a much different hypothesis from identity of treatments. Let us suppose that we have sampled some values from the two populations.

If we have just as many values from the first population as from the second population, then we can randomly match them into pairs, each pair having one value from each of the two populations. Let us then score +1 when the second value is greater than the first value, and -1 when the second is less than the first. By null hypothesis they cannot tie. The famous sign test can be used. There is nothing new about this.

If instead we have more values from the second population than from the first, things are more complicated. Some of the values from the first population must have two partners instead of one. When that happens, let the value from the first population be called X, and let the two values from the second population be called Y and Z. Then there are four possibilities for the orders of the values. Here is a table showing them and their probabilities:

Y<X Y>X
Z<X a b 1/2
Z>X c d 1/2
1/2 1/2
Here the letters a, b, c, and d are joint probabilities, and the 1/2’s in the margins are marginal probabilities. For example, b is the probability that Y>X and Z<X. For example, the probability that Y<X is 1/2. There is no reason for this table to have independence. However, b+a=1/2 and b+d=1/2, so that a=d. Let us score +2 if Y>X and Z>X. Let us score -2 if Y<X and Z<X. These two scores have equal probability. Let us score zero otherwise.

The scoring should, of course, be done by a computer, not by a human. For example, let the values in the first sample be 1.2, 4.3, 5.7, 0.9, and 3.2 . Let the values in the second sample be 5.3, 7.2, 8.4, 6.7, 11.5, 9.8, and 5.9 . (There is not any need for these values to be integers.) Also, we need an arbitrary nonnegative six-digit integer to be the seed of the randomness for the random matching, so let us use 132743 . (If the user’s seed is negative or noninteger, it will be silently changed.) I furnish a JavaScript function called “twoSample” to convert these into the kind of array needed by the program of this file. Here is what to put into the upper text area:

twoSample( [1.2, 4.3, 5.7, 0.9, 3.2], [5.3, 7.2, 8.4, 6.7, 11.5, 9.8, 5.9], 132743 )
The user is respectfully invited. And, yes, twoSample can correctly handle the case where the first sample has more values than the second sample, instead of fewer. To top.
A different null hypothesis for two-sample.
The above null hypothesis asserts impossibility of ties between X and Y and between X and Z. (Ties between Y and Z are perfectly okay.) Sometimes ties cannot be prevented. One needs a different null hypothesis, which allows the ties. Such a null hypothesis is easy to imagine. Let P and Q be real-valued random variables which are symmetric around a common center of symmetry. Let R be a real-valued continuous monotonic strictly increasing function defined on the real line. Then let the null hypothesis assert that the first population has a random variable R(P), and that the second population has a random variable R(Q). All that remains is to give the scoring. If Y and Z are both greater than X, score +2. If Y and Z are both less than X, score -2. If Y and Z are on opposite sides of X, score zero. If Y and Z both equal X, score zero. If one of Y and Z is equal to X but the other is greater, score +1. If one of Y and Z is equal to X but the other is less, score -1. The twoSample function can do this scoring correctly. It is a convenient thing that the twoSample function can also correctly handle the case of more than two partners. Here is an example:
twoSample( [1.2, 4.3, 5.7, 0.9, 3.2], [5.3, 7.2, 8.4, 6.7, 11.5, 9.8, 5.9, 1e6, 5.8, 13.0, 10.7, 10.6, 8.1], 132743 )
The user is respectfully invited. To top.

Trend.

The main idea of the test of this paragraph is lifted from the famous Cox and Stuart tests for trend in a time series, but I have made changes. See Cox, D. R. and Stuart, A. (1955) Some quick sign tests for trend in location and dispersion. Biometrika, 42, 80. Any mistakes are mine, not Cox’s or Stuart’s. Let the time variable of a time series be t and the measurement at t be y, where y must be an integer. Let the null hypothesis assert that the y’s are distributed symmetrically around a common center, but that the distributions may depend on t. It is a convenient thing that the program of the present file can test such a null hypothesis against an alternative hypothesis that there is trend with respect to time. Suppose, for example, that the measurements y in a time series are 1, 2, 4, 3, 5, 6, 9, 8, 8, 10, 9, 6, 8, and 5. Suppose also that these are measured at equal time intervals. Are the measurements going up, or is this mere appearance? We pair measurements made before the middle time:
1, 2, 4, 3, 5, 6, 9,
with measurements made after the middle time:
                                8, 8, 10, 9, 6, 8, 5
in such a way that each pair has the same time difference. For example, we pair 1 with 8, 2 with 8, 4 with 10 and so on. Then we subtract measurements in the same pair, greater time minus smaller time. (Cox and Stuart use only the sign of the difference.) “We” means the computer, of course; a function called “trend” is called to do all the pairing and subtracting. Here is the call:
trend( [1, 2, 4, 3, 5, 6, 9, 8, 8, 10, 9, 6, 8, 5] )
The user is respectfully invited. If the measurements are not integers, or if some appear to be outliers, then a function called “rank” can be used:
trend( rank( [1, 2, 4, 3, 5, 6, 9, 8, 8, 10, 9, 6, 8, 5] ) )
To top.

Run a JavaScript program.

While building this page I needed a way to run little JavaScript programs, so I constructed the “Run a JavaScript program” button. When I was done I left the button so users can practice JavaScript programming with it. If a program is in the upper text area, the button will run it. Here is a trivial example:
var x=[];
for(var j=0;j<10;j++)x[j]=j;
x;
The user is respectfully invited. To top.

The “Insert commas” button.

It may be that the user is bringing in data copied from other web pages, or from files, and is pasting the data from the clipboard to the upper text area. In that case the numbers are perhaps separated by blanks or tabulation characters or the like instead of by commas. The “Insert commas” button is meant to change such other separators to commas. The button does not always guess rightly what is expected of it, so the user is respectfully asked to look at the button’s work to make sure everything is as desired. It is a good idea to type the left and right square brackets before clicking the “Insert commas” button. To top.

License, revision date, and e-mail address.

Darwin’s table is perhaps copyrighted by his publisher or perhaps by Fisher’s publisher. The remainder of this file, including the program, is in the public domain. The date of this revision is 5 March 2012. Criticism both constructive and destructive comes to me, Harold Kaplan,
       at     dot        
smtw2gh  gmail   com
Harold Kaplan’s statistics.htm
John C. Pezzullo’s page
To top.