Repository: freedeaths/mathbox-py (language: python)

Issue:
[bug and feat]: 1 bug and several features
- [x] fix bug: the "std" function in the previous version is "var". fix it and add the true "std" function, which affects the outlier module.
- [x] interpolation: linear

~~replacing null/nil/NaN/none~~ <-- next time maybe


Discussion / hints:

Fix patch:
diff --git a/examples/outlier_decomposition.py b/examples/outlier_decomposition.py
index add410c..f382955 100644
--- a/examples/outlier_decomposition.py
+++ b/examples/outlier_decomposition.py
@@ -18,7 +18,7 @@
 
     moved_seasonality = [x / y for x, y in zip(moved_trend, seasonality)]
 
-    outlier = noise_outlier(moved_seasonality, 6)
+    outlier = noise_outlier(moved_seasonality, 3)
 
     fig, axs = plt.subplots(4, 1)
     axs[0].plot(timeseries, 'b')
diff --git a/mathbox/na/interpolation.py b/mathbox/na/interpolation.py
index e69de29..62bd3b7 100644
--- a/mathbox/na/interpolation.py
+++ b/mathbox/na/interpolation.py
@@ -0,0 +1,28 @@
+def point_linear_interp(x, x_1, y_1, x_2, y_2):
+    return (y_2 - y_1) / (x_2 - x_1) * (x - x_1) + y_1
+
+"""
+extrapolation methods:
+    saturation
+"""
+def series_linear_interp(orig_time, orig_signal, desired_time, exterp="saturation"):
+    result = []
+    for item in desired_time:
+        if item < orig_time[0]:
+            if exterp == "saturation":
+                result.append(orig_signal[0])
+            elif exterp == "linear":
+                result.append(point_linear_interp(item, orig_time[0], orig_signal[0], orig_time[1], orig_signal[1]))
+        if item > orig_time[-1]:
+            if exterp == "saturation":
+                result.append(orig_signal[-1])
+            elif exterp == "linear":
+                result.append(point_linear_interp(item, orig_time[-2], orig_signal[-2], orig_time[-1], orig_signal[-1]))
+        for i in range(len(orig_time) - 1):
+            if orig_time[i] <= item and item <= orig_time[i + 1]:
+                result.append(point_linear_interp(item, orig_time[i], orig_signal[i], orig_time[i + 1], orig_signal[i + 1]))
+                break
+    return result
+
+def fill_null(time, signal):
+    pass
\ No newline at end of file
diff --git a/mathbox/statistics/estimator.py b/mathbox/statistics/estimator.py
index e03d988..3757393 100644
--- a/mathbox/statistics/estimator.py
+++ b/mathbox/statistics/estimator.py
@@ -7,12 +7,18 @@ def mean(samples):
 ddof == 1 provides an unbiased estimator of the variance of the infinite population.
 ddof == 0 provides a maximum likelihood estimate of the variance for normally distributed variables.
 """
-def std(samples, ddof=1):
+def var(samples, ddof=1):
     if ddof != 1 and ddof != 0:
         raise ValueError("ddof must be 0 or 1")
     x_bar = mean(samples)
     return sum([(x - x_bar) ** 2 for x in samples]) / (len(samples) - ddof)
 
+def std(samples, ddof=1):
+    if ddof != 1 and ddof != 0:
+        raise ValueError("ddof must be 0 or 1")
+    return var(samples, ddof=ddof) ** 0.5
+
+
 def median(samples) :
     samples = sorted(samples)
     if len(samples) % 2 == 0:
diff --git a/setup.py b/setup.py
index 4022f5b..2a4d162 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 setup(
     name='mathbox',
     python_requires='>=3.8.0',
-    version='0.0.4',
+    version='0.0.5',
     description="A math toolbox.",
     author='freedeaths',
     author_email='register917@gmail.com',


Test patch:
diff --git a/mathbox/na/tests/__init__.py b/mathbox/na/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/mathbox/na/tests/test_interpolation.py b/mathbox/na/tests/test_interpolation.py
new file mode 100644
index 0000000..500bc15
--- /dev/null
+++ b/mathbox/na/tests/test_interpolation.py
@@ -0,0 +1,17 @@
+from pytest import approx
+
+from ..interpolation import *
+
+
+def test_point_linear_interp():
+    sig_1 = (0, 1)
+    sig_2 = (1, 2)
+    assert point_linear_interp(1.5, sig_1[0], sig_1[1], sig_2[0], sig_2[1]) == 2.5
+    assert point_linear_interp(.5, sig_1[0], sig_1[1], sig_2[0], sig_2[1]) == 1.5
+
+def test_series_linear_interp():
+    orig_time = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    orig_signal = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    desired_time = [-2, -1, 0, 1, 2, 3, 5, 6, 8, 9, 10]
+    assert series_linear_interp(orig_time, orig_signal, desired_time, "linear") == desired_time
+    assert series_linear_interp(orig_time, orig_signal, desired_time) == [0, 0, 0, 1, 2, 3, 5, 6, 8, 9, 9]
\ No newline at end of file
diff --git a/mathbox/statistics/tests/test_estimator.py b/mathbox/statistics/tests/test_estimator.py
index 6e266cd..d2da682 100644
--- a/mathbox/statistics/tests/test_estimator.py
+++ b/mathbox/statistics/tests/test_estimator.py
@@ -7,9 +7,13 @@ def test_mean():
     assert mean([1,2,3,4,5]) == 3.0
     assert mean([1.0,2.0,3.0,4.0,5.0]) == 3.0
     
+def test_var():
+    assert var([1,2,3,4,5],ddof=1) == 2.5
+    assert var([1,2,3,4,5],ddof=0) == 2.0
+
 def test_std():
-    assert std([1,2,3,4,5],ddof=1) == 2.5
-    assert std([1,2,3,4,5],ddof=0) == 2.0
+    assert std([1,2,3,4,5],ddof=1) == approx(1.5811, abs=0.001)
+    assert std([1,2,3,4,5],ddof=0) == approx(1.4142, abs=0.001)
 
 def test_median():
     assert median([1,2,4,7,6]) == 4