11import pytest
22import numpy as np
33import pandas as pd
4- from percentify import vif
4+ from percentify import vif , missing , cv , outliers
55
66
7+ # ===== Fixtures =====
8+
79@pytest .fixture
810def independent_df ():
911 np .random .seed (42 )
@@ -25,6 +27,8 @@ def collinear_df():
2527 })
2628
2729
30+ # ===== vif =====
31+
2832def test_vif_returns_all_columns (independent_df ):
2933 result = vif (independent_df )
3034 assert set (result .keys ()) == {"a" , "b" , "c" }
@@ -77,3 +81,162 @@ def test_vif_custom_decimals(independent_df):
7781 str_val = str (val )
7882 if "." in str_val :
7983 assert len (str_val .split ("." )[1 ]) <= 4
84+
85+
86+ # ===== missing =====
87+
88+ def test_missing_basic ():
89+ df = pd .DataFrame ({
90+ "a" : [1 , 2 , None , 4 , 5 ],
91+ "b" : [None , None , 3 , 4 , 5 ],
92+ "c" : [1 , 2 , 3 , 4 , 5 ],
93+ })
94+ result = missing (df )
95+ assert result ["b" ] == 40.0
96+ assert result ["a" ] == 20.0
97+ assert result ["c" ] == 0.0
98+
99+
100+ def test_missing_sorted_descending ():
101+ df = pd .DataFrame ({
102+ "a" : [1 , 2 , None , 4 , 5 ],
103+ "b" : [None , None , 3 , 4 , 5 ],
104+ "c" : [1 , 2 , 3 , 4 , 5 ],
105+ })
106+ result = missing (df )
107+ keys = list (result .keys ())
108+ assert keys == ["b" , "a" , "c" ]
109+
110+
111+ def test_missing_no_nulls ():
112+ df = pd .DataFrame ({"a" : [1 , 2 , 3 ], "b" : [4 , 5 , 6 ]})
113+ result = missing (df )
114+ assert result ["a" ] == 0.0
115+ assert result ["b" ] == 0.0
116+
117+
118+ def test_missing_all_null ():
119+ df = pd .DataFrame ({"a" : [None , None , None ]})
120+ result = missing (df )
121+ assert result ["a" ] == 100.0
122+
123+
124+ def test_missing_empty_df ():
125+ df = pd .DataFrame ({"a" : [], "b" : []})
126+ result = missing (df )
127+ assert result ["a" ] == 0.0
128+
129+
130+ def test_missing_includes_non_numeric ():
131+ df = pd .DataFrame ({
132+ "name" : ["Alice" , None , "Charlie" ],
133+ "age" : [25 , None , 35 ],
134+ })
135+ result = missing (df )
136+ assert "name" in result
137+ assert "age" in result
138+ assert result ["name" ] == 33.33
139+ assert result ["age" ] == 33.33
140+
141+
142+ # ===== cv =====
143+
144+ def test_cv_series ():
145+ s = pd .Series ([10 , 20 , 30 , 40 , 50 ])
146+ result = cv (s )
147+ assert result > 0
148+ assert isinstance (result , float )
149+
150+
151+ def test_cv_dataframe ():
152+ df = pd .DataFrame ({
153+ "a" : [10 , 20 , 30 , 40 , 50 ],
154+ "b" : [100 , 100 , 100 , 100 , 100 ],
155+ })
156+ result = cv (df )
157+ assert isinstance (result , dict )
158+ assert result ["a" ] > 0
159+ assert result ["b" ] == 0.0
160+
161+
162+ def test_cv_zero_mean_series ():
163+ s = pd .Series ([- 1 , 0 , 1 ])
164+ with pytest .raises (ValueError ):
165+ cv (s )
166+
167+
168+ def test_cv_zero_mean_dataframe ():
169+ df = pd .DataFrame ({
170+ "a" : [- 1 , 0 , 1 ],
171+ "b" : [10 , 20 , 30 ],
172+ })
173+ result = cv (df )
174+ assert result ["a" ] == float ("inf" )
175+ assert result ["b" ] > 0
176+
177+
178+ def test_cv_ignores_non_numeric ():
179+ df = pd .DataFrame ({
180+ "a" : [10 , 20 , 30 ],
181+ "name" : ["x" , "y" , "z" ],
182+ })
183+ result = cv (df )
184+ assert "name" not in result
185+ assert "a" in result
186+
187+
188+ def test_cv_custom_decimals ():
189+ s = pd .Series ([10 , 20 , 30 , 40 , 50 ])
190+ result = cv (s , decimals = 4 )
191+ str_val = str (result )
192+ if "." in str_val :
193+ assert len (str_val .split ("." )[1 ]) <= 4
194+
195+
196+ # ===== outliers =====
197+
198+ def test_outliers_series ():
199+ s = pd .Series ([1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 100 ])
200+ result = outliers (s )
201+ assert isinstance (result , float )
202+ assert result > 0
203+
204+
205+ def test_outliers_no_outliers ():
206+ s = pd .Series ([1 , 2 , 3 , 4 , 5 ])
207+ result = outliers (s )
208+ assert result == 0.0
209+
210+
211+ def test_outliers_dataframe ():
212+ df = pd .DataFrame ({
213+ "a" : [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 100 ],
214+ "b" : [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ],
215+ })
216+ result = outliers (df )
217+ assert isinstance (result , dict )
218+ assert result ["a" ] > 0
219+ assert result ["b" ] == 0.0
220+
221+
222+ def test_outliers_all_nan ():
223+ s = pd .Series ([None , None , None ])
224+ result = outliers (s )
225+ assert result == 0.0
226+
227+
228+ def test_outliers_ignores_non_numeric ():
229+ df = pd .DataFrame ({
230+ "a" : [1 , 2 , 3 , 4 , 100 ],
231+ "name" : ["x" , "y" , "z" , "w" , "v" ],
232+ })
233+ result = outliers (df )
234+ assert "name" not in result
235+ assert "a" in result
236+
237+
238+ def test_outliers_custom_multiplier ():
239+ s = pd .Series ([1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 15 ])
240+ strict = outliers (s , multiplier = 1.0 )
241+ loose = outliers (s , multiplier = 3.0 )
242+ assert strict >= loose
0 commit comments