Repository: mmngreco/IneqPy

Issue:
Hoover index
Hi, do you plan to add this index to your nice project?
The project is very useful, thanks!

Discussion:
mmngreco: Needs test

Patch:
diff --git a/src/ineqpy/inequality.py b/src/ineqpy/inequality.py
index edffbaf..b11348c 100644
--- a/src/ineqpy/inequality.py
+++ b/src/ineqpy/inequality.py
@@ -28,6 +28,7 @@ __all__ = [
     "reynolds_smolensky",
     "theil",
     "ratio_top_rest",
+    "hoover",
 ]
 
 
@@ -516,3 +517,55 @@ def ratio_top_rest(income, weights=None, data=None, top_percentage=10.0):
         r += error
 
     return t / r
+
+
+def hoover(income, weights=None, data=None):
+    """Calculate Hoover index.
+
+    The Hoover index, also known as the Robin Hood index or the Schutz index,
+    is a measure of income metrics. It is equal to the portion of the total
+    community income that would have to be redistributed (taken from the richer
+    half of the population and given to the poorer half) for there to be income
+    uniformity.
+
+    Formula:
+
+        H = 1/2 sum_i( |xi - mu| ) / sum_i(xi)
+
+    Parameters
+    ----------
+    income : array-like or str
+        This variable represent tax payment of person, if pass array-like
+        then data must be None, else you pass str-name column in `data`.
+    weights : array-like or str
+        This variable represent weights of each person, if pass array-like
+        then data must be None, else you pass str-name column in `data`.
+    data : pandas.DataFrame
+        This variable is a DataFrame that contains all data required in it's
+        columns.
+
+    Returns
+    -------
+    hoover : float
+
+    References
+    ----------
+    Hoover index : https://en.wikipedia.org/wiki/Hoover_index
+    """
+    if data is not None:
+        income, weights = utils.extract_values(data, income, weights)
+    else:
+        income = income.copy()
+        weights = weights.copy()
+
+    income, weights = utils.not_null_condition(income, weights)
+
+    # variables needed
+    mu = mean(variable=income, weights=weights)
+    f_i = utils.normalize(weights)
+    xi = f_i * income
+
+    # main calc
+    h = np.sum(abs(xi - mu)) * 0.5 / sum(xi)
+
+    return h


Test patch:
diff --git a/tests/test_inequality.py b/tests/test_inequality.py
index 88b7e79..6e527c3 100644
--- a/tests/test_inequality.py
+++ b/tests/test_inequality.py
@@ -120,7 +120,7 @@ def test_ratio_weighted_eq_unweighted(n):
     xw = []
     for xi, wi in zip(x,w):
         xw += [xi]*wi  # Create a list that contains
-    
+
     xw = np.array(xw)
 
     assert len(xw) == np.sum(w)
@@ -140,3 +140,11 @@ def test_ratio_unweighted():
     obtained = inequality.ratio_top_rest(x)
     expected = 0.22203712517848642
     assert pytest.approx(obtained) == expected
+
+
+def test_hoover_index():
+    x = np.arange(10)
+    w = np.ones(10)
+    obtained = inequality.hoover(x, w)
+    expected = 4
+    np.testing.assert_almost_equal(obtained, expected)