如何在数据框的每一列上计算修改后的 Z 分数和 IQR

How to calculate modified Z score and IQR on each column of the dataframe

我有一个数据框,我正在尝试在分析之前清理数据。

由于我的数据有点复杂,我正在放一个样本数据进行试用。

A   B  C D
30 24 13 41
30 25 14 45
30 27 15 44
30 28 16 43
31 21 12 4
31 2  17 99
3 89 99 45
78 24 0   43
35 252 12 45
36 23 13 44

我正在尝试处理异常值并尝试计算修改后的 Z 分数(中位数)和 IQR 以从数据中过滤掉异常值,以便我可以获得用于进一步分析的质量数据。

我想计算 IQR,然后计算每一列的 Z 分数,并过滤掉数据框中每一列的异常值。

到目前为止我已经尝试了一些东西,比如:

IQR:


for col in df2.columns:
    col = np.array([col])
    q1_a = np.percentile(col, 25)
    q3_a = np.percentile(col, 75)
    iqr1 = q3_a - q1_a
    print(iqr1)

修改后的 Z 分数:


for col in df2.columns:
    threshold = 3.5
    col_zscore = col +'_zscore'
    median_y = df[col].median()
    print(median_y)
    median_absolute_deviation_y = (np.abs(df2[col] - median_y)).median()
    print(median_absolute_deviation_y)
    modified_z_scores = 0.7413 *((df2[col] - median_y)/median_absolute_deviation_y)
    print(modified_z_scores)
    df2[col_zscore] = np.abs(modified_z_scores)

df2 = df2[(np.abs(df2[col_zscore]) < 3.5).all(axis=1)]
print(df2)

但没有得到正确答案。该功能不适用于每一列,并在最后创建我想要的数据框。 请帮忙。 谢谢

对于IQR问题:

  Weight    Age
0   40      20
1   62      21
2   35      19
3   29      18

如果你的数据框是这样的,你可以使用下面的代码计算 IQR。

for col in df2.columns:
    col_values = df2[col]
    col_values = np.array([col_values])
    q1_a = np.percentile(col_values, 25)
    q3_a = np.percentile(col_values, 75)
    iqr1 = q3_a - q1_a
    print(iqr1)

如果所有数据列都包含数值数据,则可以使用上述代码计算IQR,否则需要先将分类数据列编码为数值。如果您需要特定的 IQR 值,请查看 numpy percentile interpolation 参数。

对于Z_score问题:

df3 = df2
for col in df2.columns:
    threshold = 3.5
    col_zscore = col +'_zscore'
    median_y = df2[col].median()
    print(median_y)
    median_absolute_deviation_y = (np.abs(df2[col]-median_y)).median()
    print(median_absolute_deviation_y)
    modified_z_scores = 0.7413 *((df2[col] - median_y)/median_absolute_deviation_y)
    print(modified_z_scores)
    df2[col_zscore] = np.abs(modified_z_scores)

df2 = df3[(np.abs(df3[col_zscore]) < 3.5)]
print(df2)

试试上面的代码。

使用scipy:

数据:

  A    B   C   D
 30   24  13  41
 30   25  14  45
 30   27  15  44
 30   28  16  43
 31   21  12   4
 31    2  17  99
  3   89  99  45
 78   24   0  43
 35  252  12  45
 36   23  13  44

代码:

import pandas as pd
import scipy

df.apply(scipy.stats.iqr)

# output
A    4.0
B    4.5
C    3.5
D    2.0
dtype: float64

df.apply(scipy.stats.zscore)

# output
        A         B         C         D
-0.196943 -0.392191 -0.307452 -0.200009
-0.196943 -0.377930 -0.269495 -0.013954
-0.196943 -0.349407 -0.231538 -0.060468
-0.196943 -0.335145 -0.193581 -0.106981
-0.139019 -0.434976 -0.345409 -1.921013
-0.139019 -0.705944 -0.155624  2.497782
-1.760907  0.534806  2.956852 -0.013954
 2.583435 -0.392191 -0.800893 -0.106981
 0.092679  2.859432 -0.345409 -0.013954
 0.150604 -0.406453 -0.307452 -0.060468

验证 iqr:

  • df.describe()
  • 目视检查 df.describe() 输出,很容易确认 scipy.stats.iqr
  • 的结果
df.describe().loc[['25%', '75%']]

# Output
        A      B      C     D
25%  30.0  23.25  12.25  43.0
75%  34.0  27.75  15.75  45.0

df 变换(修改后的 z 分数):

  • 一个z-score是偏离均值的标准差的个数,一个数据点是。从技术上讲,它衡量的是低于或高于总体平均值的标准差有多少,即原始分数。 Z分数也称为标准分数,可以放在正态分布曲线上。
import numpy as np

def mod_z(col: pd.Series, thresh: float=3.5) -> pd.Series:
    med_col = col.median()
    med_abs_dev = (np.abs(col - med_col)).median()
    mod_z = 0.7413 * ((col - med_col) / med_abs_dev)
    mod_z = mod_z[np.abs(mod_z) < thresh]
    return np.abs(mod_z)

df_mod_z = df.apply(mod_z)

# Output
      A        B       C       D
 0.7413  0.12355  0.2471  2.2239
 0.7413  0.12355  0.2471  0.7413
 0.7413  0.61775  0.7413  0.0000
 0.7413  0.86485  1.2355  0.7413
 0.7413  0.86485  0.7413     NaN
 0.7413      NaN  1.7297     NaN
    NaN      NaN     NaN  0.7413
    NaN  0.12355     NaN  0.7413
    NaN      NaN  0.7413  0.7413
    NaN  0.37065  0.2471  0.0000

过滤后的原始数据帧:

df_filtered = df[df_mod_z >= 0]
print(df_filtered)

输出

    A     B     C     D
 30.0  24.0  13.0  41.0
 30.0  25.0  14.0  45.0
 30.0  27.0  15.0  44.0
 30.0  28.0  16.0  43.0
 31.0  21.0  12.0   NaN
 31.0   NaN  17.0   NaN
  NaN   NaN   NaN  45.0
  NaN  24.0   NaN  43.0
  NaN   NaN  12.0  45.0
  NaN  23.0  13.0  44.0