One statistical test you can do is see whether the arrival time of past votes influences the arrival time of future votes. If it does, that would strongly suggest that the votes were orchestrated in some way (e.g., a machine issuing one vote per minute, or issuing 100 votes in one minute and none for the next).
This suggests to a good null hypothesis, which is that the data are drawn from a Poisson distribution. That's our benchmark for random, independent voting patterns, where the time of one vote doesn't tell you anything about the timing of the next vote. So how do we figure out whether the data we have is Poisson-distributed?
We can try to falsify this null hypothesis--convince ourselves the data are not Poisson-distributed--by testing a statistic called index of dispersion. Basically, this measures whether the standard deviation of the data is larger or smaller than you would expect if it were a Poisson variable.
The index of dispersion is the variance (square of the standard deviation) divided by the mean. For a Poisson distribution--where voting events are independent--this ratio is always 1. If the votes are too regular and machine-like, then the variance of the vote counts, and hence the index of dispersion, will be lower. If the votes are too irregular (because they happen all at once), the index of dispersion will be higher.
We'll use just the 2-minute windows to simplify things; that means that, under the null hypothesis that the data is Poisson distributed, the number of votes in each 2-minute window comes from a Poisson distribution with the same rate parameter. We just have to find out what that rate parameter is. Our best guess is just the mean of the count in each window. I'm going to do this in Python since that's what I'm most familiar with:
In : import numpy as np
In : votes_per_time = [5, 3, 2, 5, 1, 3, 3, 4, 8, 4, 2, 3, 2, 3, 4, 2, ]
In : np.mean(votes_per_time)
So the average number of votes per window is 3.375. We can start by comparing a histogram of the plots to a true Poisson variable:
Hmm. It looks like it's a little bit underdispersed--concentrated towards the center, and away from the tails, compared to a Poisson distribution. But there's no smoking gun, so let's go on with the statistics. What's the index of dispersion?
In : np.std(votes_per_time)**2 / np.mean(votes_per_time)
So these votes are slightly more regular (less variable) than we would expect from a Poisson distribution.
But we can't stop there. Even if the votes were really random, a sample of them wouldn't necessarily have an index of dispersion of exactly one. Instead, we need to figure out how likely it would be that, if the data were really Poisson, the index of dispersion would be as low as the one we saw. To do this, we'll create a ton of fake data that we know is from a Poisson distribution, and see how its index of dispersion goes.
In : np.random.seed(1234)
In : samples = [np.random.poisson(np.mean(votes_per_time), size=len(votes_per_time))
....: for i in xrange(1000)]
In : indices = [np.std(sample) ** 2 / np.mean(sample) for sample in samples]
Here's a density plot of that distribution:
You can already probably see that 0.77 (the dashed line) is fairly close to the peak of this distribution; it doesn't look implausible that we'd see a value like that from truly Poisson data. We can quantify this by producing a confidence interval for the dispersion index under the null hypothesis--basically, if the data were truly Poisson, what's an interval we would be 90% sure the dispersion index would fall inside? We find this by calculating the 2.5th and 97.5th percentiles of how it would be distributed:
In : np.percentile(indices, [2.5, 97.5])
Out: array([ 0.38584454, 1.6878125 ])
So the index of dispersion of 0.77 that we saw above is well within the realm of possibility for truly Poisson-distributed data.
This doesn't necessarily mean that the data actually is Poisson-distributed! It might be that we just don't have a large enough sample to tell. For instance, if we saw the same index of dispersion over a sample of 1,000 2-minute windows...
In : samples2 = [np.random.poisson(np.mean(evts), size=1000) for i in xrange(1000)]
In : indices2 = [np.std(sample) ** 2 / np.mean(sample) for sample in samples2]
In : np.percentile(indices2, [2.5, 97.5])
Out: array([ 0.91544624, 1.0890494 ])
...then we could much more confidently reject the hypothesis that our data was Poisson. But since our confidence interval with the smaller number of buckets is a lot wider, we don't have as much power to detect deviations from Poisson-ness.
To sum up: if the votes are actually different from how a bunch of independent humans would make them, we don't have enough data to tell.