Repository: lace/vg

Issue:
Add `vg.mean` method
To replace code removed in lace/polliwog#96.

Discussion:
now[bot]: 
This pull request is being automatically deployed with ZEIT Now ([learn more](https://zeit.co/docs/v2/integrations/now-for-github?utm_source=automated&utm_medium=github&utm_campaign=now_bot)).
To see the status of your deployment, click on the icon next to each commit.
	

Patch:
diff --git a/vg/core.py b/vg/core.py
index a0be949..0c3867b 100644
--- a/vg/core.py
+++ b/vg/core.py
@@ -28,6 +28,7 @@ __all__ = [
     "farthest",
     "basis",
     "within",
+    "average",
     "cross",
     "dot",
 ]
@@ -601,6 +602,33 @@ def within(points, radius, of_point, atol=1e-08, ret_indices=False):
         return points_within_radius
 
 
+def average(values, weights=None, ret_sum_of_weights=False):
+    """
+    Compute a weighted or unweighted average of the 3D input values. The
+    inputs could be points or vectors.
+
+    Args:
+        values (np.arraylike): A `kx3` stack of vectors.
+        weights (array-convertible): An optional `k` array of weights.
+        ret_sum_of_weights (bool): When `True`, the sum of the weights is
+            returned. When `weights` is `None`, this is the number of
+            elements over which the average is taken.
+
+    Returns:
+        np.ndarray: A `(3,)` vector with the weighted or unweighted average.
+    """
+    k = check(locals(), "values", (-1, 3))
+    if weights is not None:
+        weights = np.array(weights)
+        check(locals(), "weights", (k,))
+    result = np.average(values, axis=0, weights=weights)
+    if ret_sum_of_weights:
+        sum_of_weights = np.sum(weights)
+        return result, sum_of_weights
+    else:
+        return result
+
+
 def dot(v1, v2):
     """
     Compute individual or pairwise dot products.


Test patch:
diff --git a/vg/test_average.py b/vg/test_average.py
new file mode 100644
index 0000000..9a39ab8
--- /dev/null
+++ b/vg/test_average.py
@@ -0,0 +1,22 @@
+import numpy as np
+from . import core as vg
+
+
+def test_average():
+    np.testing.assert_array_equal(
+        vg.average(np.array([[1.0, 2.0, 3.0], [-6.0, -9.0, -15.0]])),
+        np.array([-2.5, -3.5, -6.0]),
+    )
+    np.testing.assert_array_equal(
+        vg.average(np.array([[1.0, 2.0, 3.0], [-6.0, -9.0, -15.0]]), weights=(3, 5)),
+        np.array([-3.375, -4.875, -8.25]),
+    )
+    result, sum_of_weights = vg.average(
+        np.array([[1.0, 2.0, 3.0], [-6.0, -9.0, -15.0]]),
+        weights=(3, 5),
+        ret_sum_of_weights=True,
+    )
+    np.testing.assert_array_equal(
+        result, np.array([-3.375, -4.875, -8.25]),
+    )
+    assert sum_of_weights == 8.0