import numpy as np
import pytest
import scirs2
class TestDispersionBasics:
def test_mean_abs_deviation_basic(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.mean_abs_deviation_py(data)
assert abs(result - 1.2) < 0.001
def test_mean_abs_deviation_with_center(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.mean_abs_deviation_py(data, center=2.0)
assert abs(result - 1.4) < 0.001
def test_median_abs_deviation_basic(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.median_abs_deviation_py(data)
assert abs(result - 1.0) < 0.001
def test_median_abs_deviation_with_center(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.median_abs_deviation_py(data, center=2.0)
assert abs(result - 1.0) < 0.001
def test_median_abs_deviation_with_scale(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.median_abs_deviation_py(data, scale=2.0)
assert abs(result - 2.0) < 0.001
def test_data_range_basic(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.data_range_py(data)
assert abs(result - 4.0) < 0.001
def test_coef_variation_basic(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.coef_variation_py(data)
assert abs(result - 0.527) < 0.01
def test_coef_variation_with_ddof(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result_ddof0 = scirs2.coef_variation_py(data, ddof=0)
result_ddof1 = scirs2.coef_variation_py(data, ddof=1)
assert result_ddof0 < result_ddof1
def test_gini_coefficient_basic(self):
equal_data = np.array([1.0, 1.0, 1.0, 1.0, 1.0])
result_equal = scirs2.gini_coefficient_py(equal_data)
assert abs(result_equal - 0.0) < 0.001
unequal_data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result_unequal = scirs2.gini_coefficient_py(unequal_data)
assert result_unequal > 0.2
class TestDispersionOptionalParameters:
def test_mean_abs_deviation_none_center(self):
data = np.array([2.0, 4.0, 6.0, 8.0, 10.0])
result_none = scirs2.mean_abs_deviation_py(data, center=None)
result_explicit = scirs2.mean_abs_deviation_py(data, center=6.0)
assert abs(result_none - result_explicit) < 0.001
def test_median_abs_deviation_both_params(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
result = scirs2.median_abs_deviation_py(data, center=3.0, scale=1.4826)
assert abs(result - 1.4826) < 0.001
def test_coef_variation_ddof_values(self):
data = np.array([10.0, 20.0, 30.0, 40.0, 50.0])
result_0 = scirs2.coef_variation_py(data, ddof=0)
result_1 = scirs2.coef_variation_py(data, ddof=1)
result_2 = scirs2.coef_variation_py(data, ddof=2)
assert result_0 < result_1 < result_2
class TestDispersionEdgeCases:
def test_single_value(self):
data = np.array([5.0])
mad = scirs2.mean_abs_deviation_py(data)
assert abs(mad - 0.0) < 0.001
median_mad = scirs2.median_abs_deviation_py(data)
assert abs(median_mad - 0.0) < 0.001
range_val = scirs2.data_range_py(data)
assert abs(range_val - 0.0) < 0.001
def test_identical_values(self):
data = np.array([7.0, 7.0, 7.0, 7.0, 7.0])
mad = scirs2.mean_abs_deviation_py(data)
assert abs(mad - 0.0) < 0.001
median_mad = scirs2.median_abs_deviation_py(data)
assert abs(median_mad - 0.0) < 0.001
range_val = scirs2.data_range_py(data)
assert abs(range_val - 0.0) < 0.001
cv = scirs2.coef_variation_py(data)
assert abs(cv - 0.0) < 0.001
gini = scirs2.gini_coefficient_py(data)
assert abs(gini - 0.0) < 0.001
def test_two_values(self):
data = np.array([1.0, 5.0])
mad = scirs2.mean_abs_deviation_py(data)
assert abs(mad - 2.0) < 0.001
range_val = scirs2.data_range_py(data)
assert abs(range_val - 4.0) < 0.001
def test_negative_values(self):
data = np.array([-5.0, -3.0, -1.0, 1.0, 3.0, 5.0])
mad = scirs2.mean_abs_deviation_py(data)
assert mad >= 0.0
median_mad = scirs2.median_abs_deviation_py(data)
assert median_mad >= 0.0
range_val = scirs2.data_range_py(data)
assert abs(range_val - 10.0) < 0.001
def test_extreme_inequality(self):
data = np.array([0.0, 0.0, 0.0, 0.0, 100.0])
gini = scirs2.gini_coefficient_py(data)
assert gini >= 0.8
class TestDispersionNumericalProperties:
def test_large_values(self):
data = np.array([1000.0, 2000.0, 3000.0, 4000.0, 5000.0])
mad = scirs2.mean_abs_deviation_py(data)
assert mad > 0.0
range_val = scirs2.data_range_py(data)
assert abs(range_val - 4000.0) < 0.01
def test_small_values(self):
data = np.array([0.001, 0.002, 0.003, 0.004, 0.005])
mad = scirs2.mean_abs_deviation_py(data)
assert mad > 0.0
assert mad < 0.01
range_val = scirs2.data_range_py(data)
assert abs(range_val - 0.004) < 0.0001
def test_different_scales(self):
data1 = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
data2 = np.array([10.0, 20.0, 30.0, 40.0, 50.0])
cv1 = scirs2.coef_variation_py(data1)
cv2 = scirs2.coef_variation_py(data2)
assert abs(cv1 - cv2) < 0.001
def test_many_values(self):
np.random.seed(42)
data = np.random.randn(1000) * 10 + 50
mad = scirs2.mean_abs_deviation_py(data)
assert mad > 0.0
median_mad = scirs2.median_abs_deviation_py(data)
assert median_mad > 0.0
range_val = scirs2.data_range_py(data)
assert range_val > 0.0
cv = scirs2.coef_variation_py(data)
assert cv > 0.0
gini = scirs2.gini_coefficient_py(np.abs(data)) assert 0.0 <= gini <= 1.0
class TestDispersionRealWorldScenarios:
def test_income_inequality(self):
incomes = np.array([20.0, 25.0, 30.0, 35.0, 40.0, 50.0, 60.0, 80.0, 120.0, 200.0])
gini = scirs2.gini_coefficient_py(incomes)
assert 0.2 < gini < 0.6
def test_quality_control_range(self):
measurements = np.array([99.8, 100.1, 99.9, 100.2, 100.0, 99.7, 100.3])
range_val = scirs2.data_range_py(measurements)
assert range_val < 1.0 assert abs(range_val - 0.6) < 0.01
def test_coefficient_variation_consistency(self):
process_a = np.array([100.0, 102.0, 98.0, 101.0, 99.0]) process_b = np.array([100.0, 110.0, 90.0, 105.0, 95.0])
cv_a = scirs2.coef_variation_py(process_a)
cv_b = scirs2.coef_variation_py(process_b)
assert cv_a < cv_b
def test_median_mad_robustness(self):
normal_data = np.array([10.0, 11.0, 12.0, 13.0, 14.0])
outlier_data = np.array([10.0, 11.0, 12.0, 13.0, 100.0])
mad_normal = scirs2.mean_abs_deviation_py(normal_data)
mad_outlier = scirs2.mean_abs_deviation_py(outlier_data)
median_mad_normal = scirs2.median_abs_deviation_py(normal_data)
median_mad_outlier = scirs2.median_abs_deviation_py(outlier_data)
mad_change = abs(mad_outlier - mad_normal) / mad_normal
median_mad_change = abs(median_mad_outlier - median_mad_normal) / median_mad_normal
assert median_mad_change < mad_change
def test_temperature_variability(self):
temps = np.array([18.5, 20.2, 19.8, 21.5, 19.0, 22.0, 20.5])
range_val = scirs2.data_range_py(temps)
assert 3.0 < range_val < 4.0
mad = scirs2.mean_abs_deviation_py(temps)
assert mad > 0.5
cv = scirs2.coef_variation_py(temps)
assert cv < 0.1
def test_stock_price_volatility(self):
stable_stock = np.array([100.0, 101.0, 99.0, 100.5, 100.2])
volatile_stock = np.array([100.0, 115.0, 95.0, 110.0, 90.0])
cv_stable = scirs2.coef_variation_py(stable_stock)
cv_volatile = scirs2.coef_variation_py(volatile_stock)
assert cv_volatile > 2 * cv_stable
def test_wealth_distribution(self):
equal_wealth = np.array([100.0, 100.0, 100.0, 100.0, 100.0])
gini_equal = scirs2.gini_coefficient_py(equal_wealth)
assert abs(gini_equal - 0.0) < 0.001
moderate_wealth = np.array([50.0, 75.0, 100.0, 125.0, 150.0])
gini_moderate = scirs2.gini_coefficient_py(moderate_wealth)
assert 0.1 < gini_moderate < 0.4
high_wealth = np.array([10.0, 20.0, 30.0, 40.0, 900.0])
gini_high = scirs2.gini_coefficient_py(high_wealth)
assert gini_high > 0.6
class TestDispersionComparisons:
def test_mad_vs_median_mad(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0])
mad = scirs2.mean_abs_deviation_py(data)
median_mad = scirs2.median_abs_deviation_py(data)
assert mad > 0.0
assert median_mad > 0.0
assert abs(mad - median_mad) / mad < 0.5
def test_range_bounds_other_measures(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
range_val = scirs2.data_range_py(data)
mad = scirs2.mean_abs_deviation_py(data)
median_mad = scirs2.median_abs_deviation_py(data)
assert mad < range_val
assert median_mad < range_val
def test_gini_consistency(self):
equal = np.array([1.0, 1.0, 1.0, 1.0])
slightly_unequal = np.array([1.0, 2.0, 3.0, 4.0])
very_unequal = np.array([1.0, 1.0, 1.0, 97.0])
gini_equal = scirs2.gini_coefficient_py(equal)
gini_slight = scirs2.gini_coefficient_py(slightly_unequal)
gini_very = scirs2.gini_coefficient_py(very_unequal)
assert gini_equal < gini_slight < gini_very
assert 0.0 <= gini_equal <= 1.0
assert 0.0 <= gini_slight <= 1.0
assert 0.0 <= gini_very <= 1.0
if __name__ == "__main__":
pytest.main([__file__, "-v"])