One possible route would be to get the historical price data from Yahoo and use disparities between the Close returns and the Adjusted Close returns, given a certain threshold value, and where the disparity passes that threshold is where the splits have occurred. Find the Close returns where that condition was met, maybe round the number to the nearest integer, and you have your stock split ratio.
If you choose a viable threshold value, then you could find a giant list of stocks, automate the process of importing the data and running the computation for all of them, storing the split ratios in a CSV or a database. Then you just open up that data, make a histogram, and there you have it.
This isn't the most robust method in the world, but it gets the job done if you want to get a rough idea of the pattern.
Say we want to find the splits in Apple's stock history. I don't know what language you program in, but right now I have R open so I'll just do it in R and comment my code so hopefully it's clear what I'm doing. Here I'm using a threshold of 1.5, so that if the Close returns 1.5 times greater than the Adjusted Close returns, it gets picked out of the data so we can zero in on it and find the split ratio.
# Import the price data from Yahoo
# (This is a custom function I wrote for myself that pulls the entire price
# history from Yahoo for a given ticker)
aapl = stock('aapl')
# Isolate the Close and Adjusted Close prices (columns 5 and 7, respectively)
dates = as.Date(aapl[,1])
close = aapl[,5]
adjcl = aapl[,7]
N = length(close) # number of rows of data
# Compute the daily returns of each array
closeReturns = (close[2:N] / close[1:(N-1)])
adjclReturns = (adjcl[2:N] / adjcl[1:(N-1)])
# Pick a threshold for how much they have to differ to be picked up
threshold = 1.5 # arbitrary guess, but it works for Apple
# Find the array indices where the returns differ by at least the threshold
splitLocations = which(closeReturns > threshold * adjclReturns, arr.ind=T)
# Find the close returns where the splits happened, and round to nearest integer
splitRatios = round(closeReturns[splitLocations])
# Find the dates where the splits happened
splitDates = dates[splitLocations]
# Put them next to each other so we can see the date and magnitude of each split
splits = cbind(data.frame(splitDates), splitRatios)
# Print the results
1 2014-06-09 7
2 2005-02-28 2
3 2000-06-21 2
4 1987-06-16 2
To verify that this is right, looking at chart on Yahoo Finance, Apple's stock had the following splits:
- 7:1 on Jun 09, 2014
- 2:1 on Feb 28, 2005
- 2:1 on Jun 21, 2000
- 2:1 on Jun 16, 1987
So it works for Apple. Definitely do some double-checking and such before you unleash it on aggregating all the split data, but this is one possible route you could take. The problem here is that it would miss things like 1.5:1 splits and reverse stock splits, hence why it isn't that "robust."
But the next step would be to compile all the tickers you want to look at, import the data, run the algo, store the ratios in a CSV, and then find the distribution of those ratios.