<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Regression
Intro
Ordinary Least Squares (OLS)
OLS is a common regression method of estimating unknown parameters in linear models. This method is designed to minimize the sum of squared errors (sum of squared differences between observed and predicted response values), in order to produce a linear model with parameters that best fit the data. To illustrate this, the following figure shows a collection of data points (blue dots), and a line of best fit (solid blue line) determined using OLS, which is our linear model. 
The data points fall above, below, and sometimes right on the line. The vertical distance between a data point and the line (at the point of our prediction) is the error. There are two dotted-red vertical lines to show this error.
Assumptions
The ordinary least squares method assumes several conditions to be true (don't worry too much about these right now)
Step1:  Read data files to dict
Step2:  EDA
Function to print data info and summary stats
Step3:  Batting
Summary Stats
Step4:  Pair Plots
<ASSISTANT_TASK:>
Python Code:
e = np.random.randn(50)
w = 3
x = np.random.rand(50)*np.random.randint(0,10,50)
y = w*x + 2*e
x
x[41], y[41]
sns.regplot(x, y, ci=False)
plt.plot((x[25], x[25]), (13, y[25]-0.3), 'r:');
plt.plot((x[41], x[41]), (y[41]+0.3, 14.5), 'r:');
import pandas as pd
from pandas import DataFrame as DF, Series
import numpy as np
import scipy.stats as st
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
gnbu = sns.color_palette('GnBu', 40)
sns.set_style('whitegrid')
Explanation: Regression
Intro
Ordinary Least Squares (OLS)
OLS is a common regression method of estimating unknown parameters in linear models. This method is designed to minimize the sum of squared errors (sum of squared differences between observed and predicted response values), in order to produce a linear model with parameters that best fit the data. To illustrate this, the following figure shows a collection of data points (blue dots), and a line of best fit (solid blue line) determined using OLS, which is our linear model. 
The data points fall above, below, and sometimes right on the line. The vertical distance between a data point and the line (at the point of our prediction) is the error. There are two dotted-red vertical lines to show this error.
Assumptions
The ordinary least squares method assumes several conditions to be true (don't worry too much about these right now):
The response (dependent) variable $Y$ has a linear relationship with the independent variables in $X$, where $X$ is a design matrix (each column in the matrix is a vector of an independent variable).
The independent variables in $X$ must all be linearly independent. Simply put, there should be no $X_i = bX_j$ for $i \neq j$ in $X$.
The residuals of the model should have no heterscedasticity (i.e. variance should remain the same in the residuals no matter the X values.
The conditional mean of the errors should be zero ($E [\varepsilon|X] = 0$). This really just says the mean of the error terms should be zero, and there should be no relationship between the $X$-values and the error.
The error terms should follow a normal distribution
The data should be from a random sample
Condition (2) is always true in the bivariate case (see next section)
The OLS Regression Equations
The simplest form of OLS is the bivariate case, where we have only one independent variable and the dependent variable:
$$\hat y = b_0 + b_1x + \varepsilon$$
$\hat y$ : the estimate for the true value $y$
$b_0$ : the y-intercept (a constant)
$b_1$ : the regression coefficient (the parameter of $x$) is the average change in $y$ for every unit change in $x$
$\varepsilon$ : the error term
Beyond this we have the multivariate case, which we refer to as multiple regression. The multiple regression models can be written in the expanded form
$$\hat y = b_0 + b_1X_1 + b_2X_2 + ... + b_nX_n + \varepsilon$$
The interpretation of this is similar to the bivariate case, only now we have a parameter for every $X_i$, and instead of a line we have what is called a hyperplane. If we had only two independent variables we would have a regular plane. The compact version of this equation is the matrix form (from linear algebra)
$$\hat y = \boldsymbol X\boldsymbol b + \varepsilon$$
Where $\boldsymbol X\boldsymbol b$ represents matrix multiplication.
A Notable Property
The regression line (or plane) intersects the means of the X and Y values.
Residual Analysis
Residuals are the true values minus predicted values (the prediction errors)
Here residual analysis will be limited to plotting the residuals (vertical-axis) vs. independent variables (horizontal-axis). Randomly scattered residuals indicate that the data is appropriate for linear regression. Any cruvature or otherapparent patterns in the residuals indicates a non-linear model would be best.
Examples
Figure (a) shows random distribution of residuals with no heteroscedasticity -- a linear model is good here.
Figure (b) residuals are not randomly distributed and the increase as the independent variable increases. This could indicate lurking variables that haven't been included in the model.
Figure (c) has non-random residuals that curve around the regression line. This can indicate the need for a polynomial fit (more on this later)
Goodness of fit
R-squared : Also called the coefficient of determination, this is an often used measure of fit that represents the proportion of variance in the response that can be accounted for by the model. The R-squared value ranges from 0 to 1.
0 indicates the response variable cannot be predicted from the independent variables
1 indicates the response variable is perfectly predicted from the independent varaibles
0.4 indicates 40% of the variance in the response varaible can be predicted from the independent variables
Tranformations
If we have residual plots that indicate non-linear data, we might be able to apply a transformation to make it more linear. Such transformations can enable us to use linear regression methods on non-linear data.
A couple transformations
Logarithmic transform
regression equation: $y = b_0 + b_1log(x)$
predicted value: same
use if X appears to be logarithmic
Exponential transform
regression equation: $log(y) = b_0 +b_1x$
predicted value: $\hat y = e^{b_0 +b_1x}$
use if X appears to be exponential 
As you can see, in cases where the transformation is applied to the dependent variable, getting the prediction in terms of the original units requires applying the inverse of the original transform. Other transforms (such as quadratic) can be used. Perhaps the most important thing to note about these transformations is that they much maintain a linear form similar to $y' = b_0 +b_1x'$ where the $'$ indicates possibly transformed versions of the original variables. Without this form, we could not fit linear models.
It will usually not be clear exactly what transformation to apply, and so you must use trial-and-error to determine the best one to use.
End of explanation
sets = ['batting',
        'pitching',
        'player',
        'salary']
data = {}
for s in sets:
    file = s + '.csv'
    data[s] = pd.read_csv(file)
Explanation: Read data files to dict
End of explanation
def summary(data):
    # data info
    print('DATA INFO \n')
    data.info()
    print(50*'-', '\n')
    # numeric summary
    print('NUMERIC \n')
    print(data.describe().T)
    print(50*'-', '\n')
    # categorical summary
    print('CATEGORICAL \n')
    print(data.describe(include=['O']).T)
# import pandas scatter_matrix to create pair-plots
from pandas.plotting import scatter_matrix
Explanation: EDA
Function to print data info and summary stats
End of explanation
summary(data['batting'])
Explanation: Batting
Summary Stats
End of explanation
# features to plot
cols = list(data['batting'].loc[:1, 'r':'rbi'].columns) + ['team_id']
cols
teams = data['batting'].team_id.value_counts().head(3).index
colors = {teams[0]: 'r', teams[1]: 'g', teams[2]: 'b'}
subset = data['batting'][data['batting'].team_id.isin(teams)][cols].sample(frac=0.15)
teams
scatter_matrix(subset, c=subset.team_id.apply(lambda x: colors[x]), alpha=0.5, figsize=(14,14));
Explanation: Pair Plots
End of explanation
<END_TASK>