Skip to main content

Section 10.4 Estimation

The parameters slope and intercept are estimates based on a sample. Like other estimates, they are vulnerable to non-representative sampling, measurement error, and variability due to random sampling. As usual, it’s hard to quantify the effect of non-representative sampling and measurement error. It’s easier to quantify the effect of random sampling.
One way to do that is a kind of resampling called bootstrapping: we’ll treat the sample as if it were the whole population and draw new samples, with replacement, from the observed data. The following function takes a DataFrame and uses the sample method to resample the rows and return a new DataFrame.
Listing 10.4.1. Python Code
def resample(df):
    n = len(df)
    return df.sample(n, replace=True)
And the following function takes a DataFrame, finds the least squares fit, and returns the slope of the fitted line.
Listing 10.4.2. Python Code
def estimate_slope(df):
    xs, ys = df["Flipper Length (mm)"], df["Body Mass (g)"]
    result = linregress(xs, ys)
    return result.slope
We can use these functions to generate many simulated datasets and compute the slope for each one.
Listing 10.4.3. Python Code
# Seed the random number generator so we get the same results every time

np.random.seed(1)
Listing 10.4.4. Python Code
resampled_slopes = [estimate_slope(resample(adelie)) for i in range(1001)]
The result is a sample from the sampling distribution of the slope. Here’s what it looks like.
Listing 10.4.5. Python Code
from thinkstats import plot_kde

plot_kde(resampled_slopes)
decorate(xlabel="Slope of the fitted line (g / mm)", ylabel="Density")
Figure 10.4.6.
We can use percentile to compute a 90% confidence interval.
Listing 10.4.7. Python Code
$ ci90 = np.percentile(resampled_slopes, [5, 95])
print(result.slope, ci90)
32.83168975115009 [25.39604591 40.21054526]
So we could report that the estimated slope is 33 grams / mm with a 90% CI [25, 40] grams / mm.
The standard error of the estimate is the standard deviation of the sampling distribution.
Listing 10.4.8. Python Code
$ stderr = np.std(resampled_slopes)
stderr
np.float64(4.570238986584832)
The RegressionResult object we got from linregress provides an approximation of the standard error, based on some assumptions about the shape of the distribution.
Listing 10.4.9. Python Code
$ result.stderr
np.float64(5.076138407990821)
The standard error we computed by resampling is a little smaller, but the difference probably doesn’t matter in practice.