Repository: sktime/sktime

Issue:
[BUG] TDistribution pdf does not consider location/scale
**Describe the bug**
The location/scale (mu/sigma) are not considered at all in methods: pdf, log_pdf, cdf or ppf

For example, the case pdf:

```    
def pdf(self, x):
        """Probability density function."""
        d = self.loc[x.index, x.columns]
        pdf_arr = gamma((d._df + 1) / 2)
        pdf_arr = pdf_arr / (np.sqrt(np.pi * d._df) * gamma(d._df / 2))
        pdf_arr = pdf_arr * (1 + x**2 / d._df) ** (-(d._df + 1) / 2)
        return pd.DataFrame(pdf_arr, index=x.index, columns=x.columns)
```

Here, in line 6, instead of x**2 one should use ((x - d._mu)/d._sigma)**2


sktime version 0.25.1


[BUG] TDistribution computes incorrectly variance 
**Describe the bug**

TDistribution does not use scale (sigma) for variance computation

```    
def var(self):
...
        df_arr = self._df.copy()
        df_arr = df_arr.astype(np.float32)
        df_arr[df_arr <= 2] = np.inf
        mask = (df_arr > 2) & (df_arr != np.inf)
        df_arr[mask] = df_arr[mask] / (df_arr[mask] - 2)
        return pd.DataFrame(df_arr, index=self.index, columns=self.columns)
```

one should correct the previous to last line to:

```
df_arr[mask] = self._sigma** 2 * df_arr[mask] / (df_arr[mask] - 2)
```

sktime version 0.25.1


Discussion:
Yes, you are right - FYI @Alex-JG3. I also apologize, I reviewed and did not notice.

Would you like to make a PR with the suggested fixes?

I think most methods are correct if `mu` is 0 and `sigma` is 1 - so we can fix quickly by:

* `pdf`: subtracting `self._mu` from `x` at the start, dividing the result by `self._sigma`
* `log_pdf`: subtracting `self._mu` from `x` at the start, subtracting `log` of `self._sigma` from the result
* `cdf`: subtracting `self._mu` from `x` at the start
* `ppf`: adding `self._mu` to the result
* `var` as you suggested in https://github.com/sktime/sktime/issues/5919
(let us know if you'd prefer someone else fixing this - I just thought since you've aready identified most fixes)
Agreed with diagnosis and proposed solution - would you like to contribute this as a PR?
> Agreed with diagnosis and proposed solution - would you like to contribute this as a PR?

Ok. I will. 

Resolving patch:
diff --git a/sktime/proba/t.py b/sktime/proba/t.py
--- a/sktime/proba/t.py
+++ b/sktime/proba/t.py
@@ -100,7 +100,7 @@ def var(self):
         df_arr = df_arr.astype(np.float32)
         df_arr[df_arr <= 2] = np.inf
         mask = (df_arr > 2) & (df_arr != np.inf)
-        df_arr[mask] = df_arr[mask] / (df_arr[mask] - 2)
+        df_arr[mask] = self._sigma[mask] ** 2 * df_arr[mask] / (df_arr[mask] - 2)
         return pd.DataFrame(df_arr, index=self.index, columns=self.columns)
 
     def pdf(self, x):
@@ -108,7 +108,10 @@ def pdf(self, x):
         d = self.loc[x.index, x.columns]
         pdf_arr = gamma((d._df + 1) / 2)
         pdf_arr = pdf_arr / (np.sqrt(np.pi * d._df) * gamma(d._df / 2))
-        pdf_arr = pdf_arr * (1 + x**2 / d._df) ** (-(d._df + 1) / 2)
+        pdf_arr = pdf_arr * (1 + ((x - d._mu) / d._sigma) ** 2 / d._df) ** (
+            -(d._df + 1) / 2
+        )
+        pdf_arr = pdf_arr / d._sigma
         return pd.DataFrame(pdf_arr, index=x.index, columns=x.columns)
 
     def log_pdf(self, x):
@@ -117,14 +120,18 @@ def log_pdf(self, x):
         lpdf_arr = loggamma((d._df + 1) / 2)
         lpdf_arr = lpdf_arr - 0.5 * np.log(d._df * np.pi)
         lpdf_arr = lpdf_arr - loggamma(d._df / 2)
-        lpdf_arr = lpdf_arr - ((d._df + 1) / 2) * np.log(1 + x**2 / d._df)
+        lpdf_arr = lpdf_arr - ((d._df + 1) / 2) * np.log(
+            1 + ((x - d._mu) / d._sigma) ** 2 / d._df
+        )
+        lpdf_arr = lpdf_arr - np.log(d._sigma)
         return pd.DataFrame(lpdf_arr, index=x.index, columns=x.columns)
 
     def cdf(self, x):
         """Cumulative distribution function."""
         d = self.loc[x.index, x.columns]
-        cdf_arr = x * gamma((d._df + 1) / 2)
-        cdf_arr = cdf_arr * hyp2f1(0.5, (d._df + 1) / 2, 3 / 2, -(x**2) / d._df)
+        x_ = (x - d._mu) / d._sigma
+        cdf_arr = x_ * gamma((d._df + 1) / 2)
+        cdf_arr = cdf_arr * hyp2f1(0.5, (d._df + 1) / 2, 3 / 2, -(x_**2) / d._df)
         cdf_arr = 0.5 + cdf_arr / (np.sqrt(np.pi * d._df) * gamma(d._df / 2))
         return pd.DataFrame(cdf_arr, index=x.index, columns=x.columns)
 
@@ -145,6 +152,7 @@ def ppf(self, p):
         ppf_arr[mask1 | mask2] = np.sqrt(ppf_arr[mask1 | mask2] - 1)
         ppf_arr[mask1 | mask2] = np.sqrt(d._df[mask1 | mask2]) * ppf_arr[mask1 | mask2]
         ppf_arr[mask1] = -ppf_arr[mask1]
+        ppf_arr = d._sigma * ppf_arr + d._mu
         return pd.DataFrame(ppf_arr, index=p.index, columns=p.columns)
 
     @classmethod


Test patch: