microdf-python 1.5.0__py3-none-any.whl → 1.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
microdf/microdataframe.py CHANGED
@@ -460,7 +460,7 @@ class MicroDataFrame(WeightPropagationMixin, pd.DataFrame):
460
460
  if inplace:
461
461
  # Snapshot weight *values* positionally — the index is about
462
462
  # to change and reset_index preserves row order.
463
- weight_values = np.asarray(self.weights.values, dtype=float)
463
+ weight_values = np.array(self.weights, dtype=float, copy=True)
464
464
  super().reset_index(
465
465
  level=level,
466
466
  drop=drop,
@@ -470,7 +470,7 @@ class MicroDataFrame(WeightPropagationMixin, pd.DataFrame):
470
470
  allow_duplicates=allow_duplicates,
471
471
  names=names,
472
472
  )
473
- self.weights = pd.Series(weight_values, index=self.index, dtype=float)
473
+ self.weights = weight_series(weight_values, self.index)
474
474
  self._link_all_weights()
475
475
  return None
476
476
  else:
@@ -483,15 +483,9 @@ class MicroDataFrame(WeightPropagationMixin, pd.DataFrame):
483
483
  allow_duplicates=allow_duplicates,
484
484
  names=names,
485
485
  )
486
- out = MicroDataFrame(res, weights=self.weights.values)
487
- # Ensure weights align to res.index (reset_index changes the
488
- # index but preserves row order, so pass values positionally).
489
- out.weights = pd.Series(
490
- np.asarray(self.weights.values, dtype=float),
491
- index=out.index,
492
- dtype=float,
493
- )
494
- return out
486
+ # Own a positional copy: reset_index changes labels but
487
+ # preserves row order.
488
+ return MicroDataFrame(res, weights=weight_series(self.weights, res.index))
495
489
 
496
490
  def copy(self, deep: Optional[bool] = True) -> "MicroDataFrame":
497
491
  return super().copy(deep)
microdf/microseries.py CHANGED
@@ -120,6 +120,16 @@ class MicroSeries(WeightPropagationMixin, pd.Series):
120
120
  super().__finalize__(other, method=method, **kwargs)
121
121
  return finalize_weights(self, other, method, previous)
122
122
 
123
+ def _construct_result(self, *args, **kwargs):
124
+ # pandas has already aligned this Series before constructing a binary
125
+ # result. Retain its row weights, even when pandas 3 also finalizes
126
+ # metadata from the other operand. Delegate values and names to pandas.
127
+ result = super()._construct_result(*args, **kwargs)
128
+ if not isinstance(result, tuple):
129
+ result.weights = weight_series(self.weights, result.index)
130
+ # divmod constructs both tuple members through this same hook.
131
+ return result
132
+
123
133
  def __setattr__(self, name, value):
124
134
  weights = self.__dict__.get("weights") if name == "index" else None
125
135
  super().__setattr__(name, value)
@@ -935,95 +945,45 @@ class MicroSeries(WeightPropagationMixin, pd.Series):
935
945
  def __getattr__(self, name: str) -> "MicroSeries":
936
946
  return MicroSeries(super().__getattr__(name), weights=self.weights)
937
947
 
938
- # operators
939
-
940
- def __add__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
941
- return MicroSeries(super().__add__(other), weights=self.weights)
942
-
943
- def __sub__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
944
- return MicroSeries(super().__sub__(other), weights=self.weights)
945
-
946
- def __mul__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
947
- return MicroSeries(super().__mul__(other), weights=self.weights)
948
-
949
- def __floordiv__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
950
- return MicroSeries(super().__floordiv__(other), weights=self.weights)
951
-
952
- def __truediv__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
953
- return MicroSeries(super().__truediv__(other), weights=self.weights)
954
-
955
- def __mod__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
956
- return MicroSeries(super().__mod__(other), weights=self.weights)
957
-
958
- def __pow__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
959
- return MicroSeries(super().__pow__(other), weights=self.weights)
960
-
961
- def __xor__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
962
- return MicroSeries(super().__xor__(other), weights=self.weights)
963
-
964
- def __and__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
965
- return MicroSeries(super().__and__(other), weights=self.weights)
966
-
967
- def __or__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
968
- return MicroSeries(super().__or__(other), weights=self.weights)
969
-
970
- def __invert__(self) -> "MicroSeries":
971
- return MicroSeries(super().__invert__(), weights=self.weights)
972
-
948
+ # Explicit reverse overrides give this subclass priority when a plain
949
+ # pandas Series is on the left. _construct_result retains aligned weights.
973
950
  def __radd__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
974
- return MicroSeries(super().__radd__(other), weights=self.weights)
951
+ return super().__radd__(other)
975
952
 
976
953
  def __rsub__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
977
- return MicroSeries(super().__rsub__(other), weights=self.weights)
954
+ return super().__rsub__(other)
978
955
 
979
956
  def __rmul__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
980
- return MicroSeries(super().__rmul__(other), weights=self.weights)
957
+ return super().__rmul__(other)
981
958
 
982
959
  def __rfloordiv__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
983
- return MicroSeries(super().__rfloordiv__(other), weights=self.weights)
960
+ return super().__rfloordiv__(other)
984
961
 
985
962
  def __rtruediv__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
986
- return MicroSeries(super().__rtruediv__(other), weights=self.weights)
963
+ return super().__rtruediv__(other)
987
964
 
988
965
  def __rmod__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
989
- return MicroSeries(super().__rmod__(other), weights=self.weights)
966
+ return super().__rmod__(other)
990
967
 
991
968
  def __rpow__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
992
- return MicroSeries(super().__rpow__(other), weights=self.weights)
969
+ return super().__rpow__(other)
993
970
 
994
971
  def __rand__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
995
- return MicroSeries(super().__rand__(other), weights=self.weights)
972
+ return super().__rand__(other)
996
973
 
997
974
  def __ror__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
998
- return MicroSeries(super().__ror__(other), weights=self.weights)
975
+ return super().__ror__(other)
999
976
 
1000
977
  def __rxor__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
1001
- return MicroSeries(super().__rxor__(other), weights=self.weights)
978
+ return super().__rxor__(other)
979
+
980
+ def __invert__(self) -> "MicroSeries":
981
+ return MicroSeries(super().__invert__(), weights=self.weights)
1002
982
 
1003
983
  def sqrt(self) -> "MicroSeries":
1004
984
  sqrt_values = np.sqrt(self._values)
1005
985
  return MicroSeries(sqrt_values, index=self.index, weights=self.weights)
1006
986
 
1007
- # comparators
1008
-
1009
- def __lt__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
1010
- return MicroSeries(super().__lt__(other), weights=self.weights)
1011
-
1012
- def __le__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
1013
- return MicroSeries(super().__le__(other), weights=self.weights)
1014
-
1015
- def __eq__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
1016
- return MicroSeries(super().__eq__(other), weights=self.weights)
1017
-
1018
- def __ne__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
1019
- return MicroSeries(super().__ne__(other), weights=self.weights)
1020
-
1021
- def __ge__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
1022
- return MicroSeries(super().__ge__(other), weights=self.weights)
1023
-
1024
- def __gt__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
1025
- return MicroSeries(super().__gt__(other), weights=self.weights)
1026
-
1027
987
  # assignment operators
1028
988
 
1029
989
  def __iadd__(self, other: Union[int, float, pd.Series]) -> "MicroSeries":
@@ -0,0 +1,195 @@
1
+ """Binary operations retain the calling Series' observation weights."""
2
+
3
+ import inspect
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ import pytest
8
+
9
+ from microdf import MicroSeries
10
+
11
+
12
+ ARITHMETIC = ["add", "sub", "mul", "truediv", "floordiv", "mod", "pow"]
13
+ LOGICAL = ["and", "or", "xor"]
14
+ COMPARISONS = ["lt", "le", "eq", "ne", "ge", "gt"]
15
+
16
+
17
+ def assert_weighted_result(result, expected, source):
18
+ assert isinstance(result, MicroSeries)
19
+ pd.testing.assert_series_equal(pd.Series(result), expected)
20
+ expected_weights = (
21
+ source.weights
22
+ if source.index.equals(expected.index)
23
+ else source.weights.reindex(expected.index)
24
+ )
25
+ pd.testing.assert_series_equal(result.weights, expected_weights)
26
+ assert result.weights is not source.weights
27
+ assert result.sum() == expected.multiply(expected_weights).sum()
28
+
29
+
30
+ @pytest.mark.parametrize(
31
+ "method",
32
+ [f"__{prefix}{op}__" for op in ARITHMETIC + LOGICAL for prefix in ["", "r"]],
33
+ )
34
+ @pytest.mark.parametrize("weighted_other", [False, True])
35
+ def test_binary_operators_align_weights_with_labels(method, weighted_other):
36
+ source = MicroSeries([10, 20], index=["b", "a"], weights=[1, 9], name="x")
37
+ other = pd.Series([2, 1], index=["a", "b"], name="x")
38
+ if weighted_other:
39
+ other = MicroSeries(other, weights=[9, 1])
40
+ expected = getattr(pd.Series(source), method)(pd.Series(other))
41
+
42
+ result = getattr(source, method)(other)
43
+
44
+ assert_weighted_result(result, expected, source)
45
+ # Addition is 22 * 9 + 11 * 1 = 209, rather than the positional 121.
46
+ if method in ["__add__", "__radd__"]:
47
+ assert result.sum() == 209
48
+ result.weights.iloc[0] = 100
49
+ np.testing.assert_array_equal(source.weights, [1, 9])
50
+ if weighted_other:
51
+ np.testing.assert_array_equal(other.weights, [9, 1])
52
+ source.weights.iloc[1] = 200
53
+ assert result.weights.iloc[0] == 100
54
+
55
+
56
+ @pytest.mark.parametrize(
57
+ "method",
58
+ ARITHMETIC + [f"r{op}" for op in ARITHMETIC] + COMPARISONS + ["div", "rdiv"],
59
+ )
60
+ @pytest.mark.parametrize("permuted", [False, True])
61
+ def test_named_binary_methods_use_calling_series_weights(method, permuted):
62
+ source = MicroSeries([10, 20], index=["b", "a"], weights=[1, 9], name="x")
63
+ other = MicroSeries(
64
+ [2, 1], index=["a", "b"] if permuted else ["b", "a"], weights=[5, 7], name="x"
65
+ )
66
+ expected = getattr(pd.Series(source), method)(pd.Series(other))
67
+
68
+ result = getattr(source, method)(other)
69
+
70
+ assert_weighted_result(result, expected, source)
71
+ # Inherited public methods keep the installed pandas API signatures.
72
+ assert inspect.signature(getattr(MicroSeries, method)) == inspect.signature(
73
+ getattr(pd.Series, method)
74
+ )
75
+
76
+
77
+ @pytest.mark.parametrize("method", [f"__{op}__" for op in COMPARISONS])
78
+ def test_comparison_operators_keep_calling_series_weights_and_pandas_errors(method):
79
+ source = MicroSeries([10, 20], index=["b", "a"], weights=[1, 9])
80
+ other = MicroSeries([20, 10], index=source.index, weights=[5, 7])
81
+ expected = getattr(pd.Series(source), method)(pd.Series(other))
82
+ assert_weighted_result(getattr(source, method)(other), expected, source)
83
+
84
+ other.index = ["a", "b"]
85
+ with pytest.raises(ValueError) as pandas_error:
86
+ getattr(pd.Series(source), method)(pd.Series(other))
87
+ with pytest.raises(ValueError) as microdf_error:
88
+ getattr(source, method)(other)
89
+ assert str(microdf_error.value) == str(pandas_error.value)
90
+
91
+
92
+ @pytest.mark.parametrize("method", ["__add__", "__rsub__", "add", "rsub", "lt"])
93
+ @pytest.mark.parametrize("operand", [3, [2, 1], np.array([2, 1])])
94
+ def test_scalar_and_array_binary_operands_keep_weights(method, operand):
95
+ source = MicroSeries([10, 20], index=["b", "a"], weights=[1, 9])
96
+ expected = getattr(pd.Series(source), method)(operand)
97
+ assert_weighted_result(getattr(source, method)(operand), expected, source)
98
+
99
+
100
+ @pytest.mark.parametrize("method", ["__add__", "__rsub__", "add", "rsub", "lt"])
101
+ def test_matching_duplicate_indexes_keep_positional_weights(method):
102
+ source = MicroSeries([10, 20, 30], index=["a", "a", "b"], weights=[1, 9, 3])
103
+ other = MicroSeries([2, 1, 4], index=source.index, weights=[5, 7, 11])
104
+ expected = getattr(pd.Series(source), method)(pd.Series(other))
105
+ assert_weighted_result(getattr(source, method)(other), expected, source)
106
+
107
+
108
+ @pytest.mark.parametrize("method", ["__divmod__", "__rdivmod__", "divmod", "rdivmod"])
109
+ def test_divmod_results_keep_calling_series_weights(method):
110
+ source = MicroSeries([10, 20], index=["b", "a"], weights=[1, 9])
111
+ other = MicroSeries([3, 4], index=["a", "b"], weights=[5, 7])
112
+ expected = getattr(pd.Series(source), method)(pd.Series(other))
113
+ result = getattr(source, method)(other)
114
+ assert isinstance(result, tuple)
115
+ for actual, plain in zip(result, expected):
116
+ assert_weighted_result(actual, plain, source)
117
+
118
+
119
+ @pytest.mark.parametrize("method", ["__add__", "__rsub__", "add", "rsub", "lt"])
120
+ @pytest.mark.parametrize(
121
+ "left_index,right_index",
122
+ [
123
+ (["b", "a"], ["a", "c"]),
124
+ (["b", "a", "b"], ["a", "b", "b"]),
125
+ ],
126
+ ids=["new-rows", "ambiguous-duplicates"],
127
+ )
128
+ def test_binary_operations_reject_unknown_row_weights(method, left_index, right_index):
129
+ source = MicroSeries(
130
+ range(len(left_index)), index=left_index, weights=range(1, len(left_index) + 1)
131
+ )
132
+ other = MicroSeries(
133
+ range(len(right_index)),
134
+ index=right_index,
135
+ weights=range(4, len(right_index) + 4),
136
+ )
137
+ with pytest.raises(ValueError, match="weights"):
138
+ getattr(source, method)(other)
139
+
140
+
141
+ @pytest.mark.parametrize("method", ["add", "rsub", "lt"])
142
+ def test_named_binary_arguments_preserve_pandas_values_and_errors(method):
143
+ index = pd.MultiIndex.from_tuples([("b", 2), ("a", 1)], names=["group", "row"])
144
+ source = MicroSeries([np.nan, 20], index=index, weights=[1, 9])
145
+ other = pd.Series([2, 1], index=pd.Index(["a", "b"], name="group"))
146
+ kwargs = {"level": "group", "fill_value": 0, "axis": "index"}
147
+ expected = getattr(pd.Series(source), method)(other, **kwargs)
148
+ assert_weighted_result(getattr(source, method)(other, **kwargs), expected, source)
149
+ for args, options in [
150
+ ((other,), {"axis": 1}),
151
+ (([1],), {}),
152
+ ((other,), {"unknown": True}),
153
+ ]:
154
+ with pytest.raises((TypeError, ValueError)) as pandas_error:
155
+ getattr(pd.Series(source), method)(*args, **options)
156
+ with pytest.raises(type(pandas_error.value)) as microdf_error:
157
+ getattr(source, method)(*args, **options)
158
+ # pandas identifies the concrete subclass in invalid-axis messages.
159
+ expected_error = str(pandas_error.value).replace(
160
+ "object type Series", "object type MicroSeries"
161
+ )
162
+ assert str(microdf_error.value) == expected_error
163
+
164
+
165
+ @pytest.mark.parametrize(
166
+ "operation",
167
+ [
168
+ lambda plain, weighted: plain + weighted,
169
+ lambda plain, weighted: plain - weighted,
170
+ lambda plain, weighted: plain * weighted,
171
+ lambda plain, weighted: plain / weighted,
172
+ lambda plain, weighted: plain // weighted,
173
+ lambda plain, weighted: plain % weighted,
174
+ lambda plain, weighted: plain**weighted,
175
+ lambda plain, weighted: plain & weighted,
176
+ lambda plain, weighted: plain | weighted,
177
+ lambda plain, weighted: plain ^ weighted,
178
+ ],
179
+ ids=ARITHMETIC + LOGICAL,
180
+ )
181
+ @pytest.mark.parametrize("indexes", ["matching", "permuted", "duplicates"])
182
+ def test_plain_series_left_expressions_preserve_weighted_dispatch(operation, indexes):
183
+ index = ["a", "a"] if indexes == "duplicates" else ["b", "a"]
184
+ source = MicroSeries([10, 20], index=index, weights=[1, 9], name="x")
185
+ other_index = ["a", "b"] if indexes == "permuted" else index
186
+ other = pd.Series([2, 1], index=other_index, name="x")
187
+ expected = operation(other, pd.Series(source))
188
+
189
+ result = operation(other, source)
190
+
191
+ assert_weighted_result(result, expected, source)
192
+ result.weights.iloc[0] = 100
193
+ np.testing.assert_array_equal(source.weights, [1, 9])
194
+ source.weights.iloc[1] = 200
195
+ assert result.weights.iloc[0] == 100
@@ -59,3 +59,50 @@ def test_stored_weight_edits_do_not_change_weight_column(dtype):
59
59
 
60
60
  np.testing.assert_array_equal(df["w"], [1, 2])
61
61
  assert df.sum()["x"] == 10 * 100 + 20 * 2
62
+
63
+
64
+ @pytest.mark.parametrize("drop", [False, True])
65
+ @pytest.mark.parametrize("inplace", [False, True])
66
+ @pytest.mark.parametrize(
67
+ "index,level",
68
+ [
69
+ (pd.Index(["b", "a", "a"], name="row"), None),
70
+ (
71
+ pd.MultiIndex.from_tuples(
72
+ [("b", 2), ("a", 1), ("a", 1)], names=["group", "row"]
73
+ ),
74
+ None,
75
+ ),
76
+ (
77
+ pd.MultiIndex.from_tuples(
78
+ [("b", 2), ("a", 1), ("a", 1)], names=["group", "row"]
79
+ ),
80
+ "group",
81
+ ),
82
+ ],
83
+ )
84
+ def test_reset_index_owns_independently_mutable_weights(index, level, drop, inplace):
85
+ source = mdf.MicroDataFrame({"x": [10, 20, 30]}, index=index, weights=[1, 9, 3])
86
+ original_weights = source.weights
87
+ expected = pd.DataFrame(source).reset_index(level=level, drop=drop)
88
+
89
+ result = source.reset_index(level=level, drop=drop, inplace=inplace)
90
+
91
+ if inplace:
92
+ assert result is None
93
+ result = source
94
+ assert isinstance(result, mdf.MicroDataFrame)
95
+ pd.testing.assert_frame_equal(pd.DataFrame(result), expected)
96
+ pd.testing.assert_series_equal(
97
+ result.weights, pd.Series([1.0, 9.0, 3.0], index=expected.index)
98
+ )
99
+ assert result.x.sum() == 10 * 1 + 20 * 9 + 30 * 3
100
+ assert result.weights is not original_weights
101
+ result.weights.iloc[0] = 100
102
+ np.testing.assert_array_equal(original_weights, [1, 9, 3])
103
+ assert result.x.sum() == 10 * 100 + 20 * 9 + 30 * 3
104
+ if not inplace:
105
+ assert source.x.sum() == 10 * 1 + 20 * 9 + 30 * 3
106
+ original_weights.iloc[1] = 200
107
+ np.testing.assert_array_equal(result.weights, [100, 9, 3])
108
+ assert result.x.sum() == 10 * 100 + 20 * 9 + 30 * 3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: microdf-python
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Weighted pandas DataFrames and Series for survey microdata
5
5
  Author-email: Max Ghenis <max@policyengine.org>
6
6
  License: MIT
@@ -1,11 +1,12 @@
1
1
  microdf/__init__.py,sha256=G4m4UDiGePngG1i0DdGYhsTAXqyDELR6Mbq72OXOMG0,790
2
2
  microdf/_weights.py,sha256=uBOcTZGmVJlzi27sSAALSTb4V9j56tXuaBfJB83x7j0,10303
3
- microdf/microdataframe.py,sha256=yJNtsm-LNyB9_nyDUpV58nUQ3iZWWT0cZsD9Eu1j22w,39711
4
- microdf/microseries.py,sha256=G56sslazw5sY1t5i8FhqtPPEU12_vQNMlmsMKw6mdkU,47633
3
+ microdf/microdataframe.py,sha256=BY5Knw4WP0TcdYM6qcSpPD1oUI9y087kxHkeyuarJoE,39475
4
+ microdf/microseries.py,sha256=0btULkhRKvMMUEtvyGaFT2aycNT_lhU1MsPXP48wlpE,45531
5
5
  microdf/replication.py,sha256=3iZ6xG24ucKofVwmXxyd7ME6rZP6iJVnN9JpWcPxg9s,7697
6
6
  microdf/tests/conftest.py,sha256=u-EMyX1-u_nM-YO0RJYCzYHQDXxUI2WQE6GkyJlErqg,150
7
7
  microdf/tests/test_aggregation_errors.py,sha256=9jJDiEyxMb2z1Zmj-o8AHDNp8LOputbEkAMefifnWaE,2013
8
- microdf/tests/test_dataframe_weight_storage.py,sha256=ngIsWa_QcBnnaLpAyIZhTgMxjv_7cK8Nbf7f4n29R4Q,1975
8
+ microdf/tests/test_binary_weight_alignment.py,sha256=d3-e7Kb6G8J22aVFTi3sOGUyDODKT1p0-XsEvMZBDvo,8115
9
+ microdf/tests/test_dataframe_weight_storage.py,sha256=m77cbDn521ehIJWbgirjhL5Q5byBdm-UZhFkGx7mp6A,3667
9
10
  microdf/tests/test_microseries_dataframe.py,sha256=vL0fg_NydU6a5myVVtXyHMr8eQOB_yyAkZYwLmoEnOA,30075
10
11
  microdf/tests/test_nullify_weights_index.py,sha256=kZgzMaZEa_PXbsor2S4E-6VRid3C3rcC9ufk0qa7mgY,341
11
12
  microdf/tests/test_pandas3_compatibility.py,sha256=A34Ni_WQ303sSNv-sqv5CGAQp54zj-ZSGAPEBHZslNI,8573
@@ -16,8 +17,8 @@ microdf/tests/test_sum_axes.py,sha256=N05ocwI5lLv2OgoaovRIqFIae-70356kZemRRet0ac
16
17
  microdf/tests/test_version_metadata.py,sha256=M1EabzHLKZZw3Djd6Zu2UuMQtDLV6rZ1zDrOU7W_jf0,227
17
18
  microdf/tests/test_weight_propagation.py,sha256=3odbufFZ2o1rnyjx6PJ7kn1TPO5K2ho3RErczI7mqO4,18761
18
19
  microdf/tests/test_weighted_cov_corr.py,sha256=LTnFhMWnb28f7L_9kOhPiV5UlLMAUbC9OlLIaZ1XgLs,13954
19
- microdf_python-1.5.0.dist-info/licenses/LICENSE,sha256=uPs-ASYnzlldpf2z8jeRgQFeEH3FLhSuX0rw0OKWoDU,1067
20
- microdf_python-1.5.0.dist-info/METADATA,sha256=PTg6QSQEgnWdWkUaOsnpi2aQ64yMuSmrJ8nONUC3XcI,2305
21
- microdf_python-1.5.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
22
- microdf_python-1.5.0.dist-info/top_level.txt,sha256=T2WFPTygQQMdS3GF8YpZ12DKfMGrspbZ3r7z-e3KfiM,8
23
- microdf_python-1.5.0.dist-info/RECORD,,
20
+ microdf_python-1.5.1.dist-info/licenses/LICENSE,sha256=uPs-ASYnzlldpf2z8jeRgQFeEH3FLhSuX0rw0OKWoDU,1067
21
+ microdf_python-1.5.1.dist-info/METADATA,sha256=iWnLVAQ4Ur-JthLTPsNnC3lC1xPrbz0vIKmI4oboEyo,2305
22
+ microdf_python-1.5.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
23
+ microdf_python-1.5.1.dist-info/top_level.txt,sha256=T2WFPTygQQMdS3GF8YpZ12DKfMGrspbZ3r7z-e3KfiM,8
24
+ microdf_python-1.5.1.dist-info/RECORD,,