【问题标题】:How to calculate modified Z score and IQR on each column of the dataframe如何在数据框的每一列上计算修改后的 Z 分数和 IQR
【发布时间】:2020-01-27 09:21:16
【问题描述】:

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

由于我的数据有点复杂,所以我正在试用一个示例数据。

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)

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

【问题讨论】:

  • 嘿,我想知道 0.7413 是什么?我认为修改后的 z 分数只是改变 z 分数的均值和标准,即(x-median)/median_absolute_deviation)

标签: python python-3.x dataframe outliers iqr


【解决方案1】:

使用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-score):

  • 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

【讨论】:

  • 完美!谢谢吨!
【解决方案2】:

对于 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)

试试上面的代码。

【讨论】:

  • 谢谢,IQR 非常适合您的回答。我正在尝试计算修改后的 Zscore,它考虑了中位数而不是平均值,然后只从数据帧中取出那些在 zscore 阈值内的值。谢谢
猜你喜欢
  • 1970-01-01
  • 2020-06-13
  • 2021-10-26
  • 2019-07-03
  • 2019-11-04
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多