1

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

由于我的数据有点复杂,因此我正在试用样本数据。

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 分数,并过滤掉数据框中每一列的异常值。

到目前为止,我已经尝试了几件事,例如:

二维码:


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)

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

4

2 回答 2

1

对于 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 百分位 插值参数。

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

试试上面的代码。

于 2019-09-27T05:20:35.340 回答
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 分数):

  • z分数是与平均值的标准偏差数,数据点是。从技术上讲,它是衡量低于或高于总体平均值的标准差的量度,即原始分数。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
于 2019-09-27T05:50:44.800 回答