How are p-values computed from t-values when doing regressions? I'm performing a regression analysis using the statsmodels module in Python. The regression gives both t-values and p-values for each coefficient, but I'd like to understand exactly which test is applied under the hood and how the p-values are computed.
I followed this Stack Overflow answer to compute the p-values from t-values and degrees of freedom, but I'm getting different results from the values returned by statsmodels. Why is this, and which test is employed "inside" statsmodels?
EDIT: Tried the same thing with a z-test. This gives accurate results in most cases, but still doesn't consistently yield the same results.
Minimal example in Python 3 to reproduce:
from sklearn import datasets
import statsmodels.api as sm
from scipy import stats

# Load data
data = datasets.load_iris()
X = data.data
X = sm.add_constant(X)
y = data.target

# Fit the logistic regression
est = sm.OLS(y, X)
res = est.fit()

df = res.df_model  # degrees of freedom

for t, p in zip(res.tvalues, res.pvalues):
    # Print t- and p-values returned by statsmodels
    print("Fit t-value=%.2g" % t)
    print("Fit p-value=%.2g" % p)

    # Compute p-value from the returned t-values
    p_manual = stats.t.sf(t, df=df)
    print("t-test Calculated p-value=%.2g" % p_manual)

    # Manually do a (two-tailed) z-test
    pz = stats.norm.sf(abs(t))*2
    print("z-test Calculated p-value=%.2g" % pz)

    print()

This prints the following:
Fit t-value=0.94
Fit p-value=0.35
t-test Calculated p-value=0.2
z-test Calculated p-value=0.35

Fit t-value=-1.9
Fit p-value=0.059
t-test Calculated p-value=0.93
z-test Calculated p-value=0.057

Fit t-value=-0.74
Fit p-value=0.46
t-test Calculated p-value=0.75
z-test Calculated p-value=0.46

Fit t-value=4
Fit p-value=0.00011
t-test Calculated p-value=0.0082
z-test Calculated p-value=6.8e-05

Fit t-value=6.5
Fit p-value=1.5e-09
t-test Calculated p-value=0.0015
z-test Calculated p-value=1.1e-10

 A: So, the two mistakes I made were 1) Making a one-tailed, rather than two-tailed t-test, and 2) using the number of degrees of freedom in the model (5). With 150 data points and 5 model parameters, the correct number is instead 145. The code below correctly computes the same p-values as the ones given by statsmodels.
The reason the Z-test appeared to give correct results for some parameters is that the t-distribution is very close to the normal distribution for large df's, but as the t-distribution is wider than the normal, the difference grows for larger values of t, consistent with z- and t-tests giving very different results only for the last two parameters above.
from sklearn import datasets
import statsmodels.api as sm
from scipy import stats

# Load data
data = datasets.load_iris()
X = data.data
X = sm.add_constant(X)
y = data.target

# Fit the logistic regression
est = sm.OLS(y, X)
res = est.fit()

n_datapoints = X.shape[0]
dim = X.shape[1]
df = n_datapoints - dim

for t, p in zip(res.tvalues, res.pvalues):
    # Print t- and p-values returned by statsmodels
    print("Fit t-value=%.2g" % t)
    print("Fit p-value=%.10g" % p)

    # Compute p-value from the returned t-values
    p_manual = stats.t.sf(abs(t), df=res.df_resid)*2
    print("t-test Calculated p-value=%.10g" % p_manual)

    print()

