Getting started
A first model
This page fits a linear model to a small table of flats, reads the estimates, and predicts rents for flats that are not in the table. It assumes the extension is installed.
Data
The formula functions take a data set as named columns: an associative array of column => list of values, with every column the same length. phibble’s DataFrame is also accepted, through its toModelData() method.
use function Phit\{fit_lm, predict};
$flats = [
'rent' => [1879.25, 1805.03, 2022.29, 1267.85, 1509.24, 2240.10, 959.51, 2386.54, 1655.80, 1420.00],
'area' => [74.4, 57.4, 66.4, 49.1, 45.7, 92.4, 37.0, 93.9, 61.2, 52.3],
'district' => ['north', 'south', 'north', 'east', 'south', 'north', 'east', 'south', 'east', 'south'],
];Numbers are numeric columns. Strings become a factor whose levels are sorted in byte order, so east is the reference level here. Model formulas lists every accepted column type.
Fit
$fit = fit_lm('rent ~ area + district', $flats);The formula follows R: rent is the response, and area + district adds a slope for floor area and treatment-coded indicators for the districts. An intercept is included unless the formula removes it with - 1 or + 0.
Read the result
The result is a plain PHP array. Every coefficient list follows the order of columns.
foreach ($fit['columns'] as $i => $name) {
printf("%-14s %9.2f %8.2f %7.4f [%8.2f, %8.2f]\n", $name, $fit['coefficients'][$i],
$fit['std_errors'][$i], $fit['p_values'][$i], ...$fit['conf_int'][$i]);
}(Intercept) 352.64 179.87 0.0976 [ -87.49, 792.77]
area 19.18 3.23 0.0010 [ 11.27, 27.09]
districtnorth 203.64 151.14 0.2265 [ -166.19, 573.47]
districtsouth 232.16 119.64 0.1004 [ -60.58, 524.90]
Each additional square meter adds about 19 to the expected rent. The district coefficients are differences from east.
| Key | Contents |
|---|---|
columns, named |
Coefficient names, and a name => coefficient map |
coefficients, std_errors, t_statistics, p_values |
One value per column |
conf_int |
95% intervals, [lower, upper] per column |
covariance |
The coefficient covariance matrix |
fitted, residuals |
One value per retained row |
r_squared, adj_r_squared, sigma, rss, log_likelihood, df_residual |
Fit statistics |
n_input, n_observations, n_dropped, retained_rows, dropped_rows |
Sample accounting |
diagnostics |
Solver, convergence and warnings |
printf("R-squared %.4f, sigma %.2f, %d residual df, %d of %d rows\n",
$fit['r_squared'], $fit['sigma'], $fit['df_residual'], $fit['n_observations'], $fit['n_input']);
echo json_encode($fit['diagnostics']), "\n";R-squared 0.9270, sigma 146.29, 6 residual df, 10 of 10 rows
{"converged":true,"solver":"scaled_svd","warnings":[]}
fit_glm, fit_lmer and fit_glmer return the same naming and accounting keys, with the statistics of their model. Linear and generalized linear models and mixed models list them.
Predict
predict() rebuilds the formula over new data. The response column is not needed, and the factor levels are the ones the fit saw.
$new = ['area' => [55.0, 80.0], 'district' => ['east', 'north']];
$p = predict($fit, $new, interval: 'prediction');
foreach ($p['fit'] as $i => $value) {
printf("%.2f [%.2f, %.2f]\n", $value, $p['lower'][$i], $p['upper'][$i]);
}1407.55 [991.59, 1823.51]
2090.69 [1676.97, 2504.41]
interval: 'confidence' gives intervals for the mean instead. A district the fit never saw raises an exception with code 1001. Prediction covers GLM and mixed-model predictions.
Missing values
null and NAN are missing. By default, a row with a missing value in any column the formula uses is dropped, and the fit emits one E_WARNING. With rent set to null in the third row:
Warning: Phit\fit_lm(): Phit\fit_lm dropped 1 of 10 observations with missing values (listwise deletion)
The result then reports n_observations 9, n_input 10 and dropped_rows [2], and diagnostics.warnings holds the same notice. Pass missing: 'raise' to reject missing values instead. The call then throws an Exception with code 1001 and the message missing values found with missing='raise'. Missing data defines which values count as missing and how rows are counted.
Errors
Invalid input and failed fits throw a PHP Exception. Its getCode() gives the category: 1001 for invalid input, 1002 for mismatched lengths, 1004 for a rank-deficient design, 1006 for nonconvergence, and so on. The full table is in the API overview.
From phpstats/phit@76b22f0.