检测和过滤异常值是数据清洗过程中非常重要的一步。比如你手里有个一万成人的身高数据,其中有几个3m以上,1m以下的数据,这都是属于异常值,需要被过滤掉。
我们来看下面的一组正态分布的数据:
In [109]: df = pd.DataFrame(np.random.randn(1000, 4)) In [110]: df.describe() Out[110]: 0 1 2 3 count 1000.000000 1000.000000 1000.000000 1000.000000 mean -0.001764 0.023018 0.038956 0.016735 std 0.998835 1.041113 1.025342 1.019077 min -3.035805 -3.056706 -2.857154 -2.922755 25% -0.654426 -0.695994 -0.712627 -0.702766 50% -0.005015 0.011862 0.020562 -0.041231 75% 0.660182 0.683478 0.732590 0.758038 max 3.323073 3.701470 3.280375 3.997876
如果你想找出第二列数据中绝对值大于3的元素:
In [113]: col = df[2] In [114]: col[np.abs(col) > 3] Out[114]: 30 3.091161 113 3.280375 Name: 2, dtype: float64
如果要选出所有行内有值大于3或小于-3的行,可以使用下面的any方法搭配:
In [125]: df[(np.abs(df)>3).any(1)] Out[125]: 0 1 2 3 28 0.008674 0.046048 -0.171580 3.997876 30 0.709758 -1.871982 3.091161 -0.819429 113 0.432223 -0.675313 3.280375 0.841355 169 3.323073 -0.608988 0.685795 -0.710693 177 -1.514524 -3.056706 -0.760937 1.300434 322 3.296765 0.971996 0.114804 1.855576 410 3.246140 -0.039501 1.530122 1.502243 496 -3.035805 -0.535662 0.703911 0.916483 575 -0.127245 3.701470 -0.642512 0.281001 720 3.045646 1.266809 1.263198 1.429049 799 0.523183 -0.246954 1.132868 3.141117
上面的代码怎么理解呢?首先,我们对整个df取绝对值,然后和3比较,形成一个bool的DataFrame,再使用any在行方向(参数1的作用)进行判断是否有True的存在,如果有,则保存在一个Series中,最后,用这个Series作为行号取df取出对应的行。
我们还可以将绝对值大于3的数分别设置为+3和-3,只需要使用np.sign(x)函数,这个函数根据x的符号分别生成+1和-1:
In [127]: df[np.abs(df) > 3] = np.sign(df) * 3 In [130]: df.describe() Out[130]: 0 1 2 3 count 1000.000000 1000.000000 1000.000000 1000.000000 mean -0.002640 0.022374 0.038584 0.015596 std 0.995851 1.038699 1.024224 1.015232 min -3.000000 -3.000000 -2.857154 -2.922755 25% -0.654426 -0.695994 -0.712627 -0.702766 50% -0.005015 0.011862 0.020562 -0.041231 75% 0.660182 0.683478 0.732590 0.758038 max 3.000000 3.000000 3.000000 3.000000 In [133]: (np.sign(df)*3).head() Out[133]: 0 1 2 3 0 3.0 3.0 -3.0 -3.0 1 3.0 3.0 -3.0 -3.0 2 -3.0 -3.0 -3.0 -3.0 3 -3.0 -3.0 3.0 -3.0 4 3.0 -3.0 3.0 -3.0
如果np.sign(x)函数的参数x为0,则生成0;为正数则生成1;为负数则生成-1。