I have data which I have to test to see if it comes from the Weibull distribution. I don't know the parameters so I am looking for a goodness of fit test (like the Lillefors test), preferably which I can use from Python. How can you do this?
1 Answer
A Lilliefors test should work just fine for the usual two parameter Weibull (the log of a Weibull is a location-scale family).
Another obvious test would be to look at the correlation in a Q-Q plot (akin to a Shapiro-Francia test or a Ryan-Joiner test for normality). Approximate expected quantiles for the Weibull are pretty straightforward to obtain. It would essentially correspond to a statistic based off correlation in a Weibull plot of the data. If $r$ is that correlation, typically a Shapiro-Francia test would look at $W^\prime=\log(n(1-r))$ and that looks like a suitable statistic here as well. The variance seems to be essentially constant and the mean changes smoothly with sample size while the shape is fairly stable over a wide range of $n$, so $(1-\alpha)$ quantiles of the statistic are essentially just shifted by a constant from the mean (e.g. somewhere around 0.9 for a 5% test).
I don't know of tables that exist for it but it's easy to simulate to obtain critical values to say 3 or 4 figures, or to obtain p-values to a similar accuracy. Alternatively, smooth interpolation in a small table of means should work quite well over a wide range of sample sizes.
A similar simulation strategy can be applied for the Lilliefors test but I'd expect it to have lower power against most of the alternatives you're likely to want to detect. (That is I suggest the test based on correlation in the Q-Q plot will usually be a better choice.)
The approach in either case would begin with choosing a specific Weibull distribution (because the log of a Weibull is a location-scale family, it won't make any difference which one you use for either test); you need this in order to simulate samples. I suggest the standard exponential for convenience.
As is usually the case with goodness of fit tests, in what follows larger values of the test statistic will be "more extreme"; if you have a test statistic for which smaller values are more extreme, it's easy to flip the statistic around.
Let $n$ be the sample size, and let $b$ be the number of simulations of the test statistic you choose to do (keeping in mind that the p-value will also include the statistic on the observed sample, which under the null will be another random draw), and let $q_i$ be the statistic on the $i$th pseudosample. Let $F_0$ be the distribution being tested (the one specified under the null).
The steps are as follows (in pseudocode but you should be able to adapt it to your case):
compute q[0], the statistic on the sample
for i in 1 to b-1
simulate a pseudosample of size n from F0
compute q[i], the test statistic on that pseudosample
compute p, the proportion of q's >= q[0]
You need two things for this: a function that computes the test statistic on a sample, and a function that can simulate a sample from the distribution under the null. [Note that for the Lilliefors test you're using parameter estimates for the unspecified parameters. For the Shapiro-Francia style test you don't need to fit parameters; if you're doing the Lilliefors you'll also need a function to estimate the parameters]
Sometimes people keep the sample statistic separate (in a different variable, $q_0$ say) from the pseudosamples, and then add $1$ to both the numerator and denominator in the computation of $p$ (which is your estimate of the p-value).
Note that you can compute an estimate of the standard error of $p$ since this is binomial sampling under the null. It's $\sqrt{p(1-p)/b}$. Note that to get approximately 3 figures of accuracy in the estimate of $p$, you need a margin of error below 0.001, which suggests $n$ should be in the ballpark of a million.
I think the book on goodness of fit testing by D'Agostino and Stephens may have a section on the Weibull.
-
$\begingroup$ In order to implement the Lilliefors test I will need to perform a simulation but I am not sure exactly what that would be. Could you explain in detail what simulation I would need to code up please? $\endgroup$– SimdCommented Aug 5, 2019 at 19:24
-
$\begingroup$ Added a new section. This is especially straightforward in R (just a few lines), and not much harder in python. $\endgroup$– Glen_bCommented Aug 5, 2019 at 22:51
-
$\begingroup$ It would be awesome if you could add some code too. $\endgroup$– SimdCommented Aug 15, 2019 at 5:41