python-3.x 如何使用IQR从DataFrame中删除离群值?

0md85ypi  于 2023-03-24  发布在  Python
关注(0)|答案(3)|浏览(136)

我有很多列的数据框架(大约100个功能),我想应用四分位数方法,并希望从数据框架中删除离群值。
我正在使用此链接stackOverflow
但问题是上述方法中没有一个是正确工作的
当我这样努力时

Q1 = stepframe.quantile(0.25)
Q3 = stepframe.quantile(0.75)
IQR = Q3 - Q1
((stepframe < (Q1 - 1.5 * IQR)) | (stepframe > (Q3 + 1.5 * IQR))).sum()

它给了我这个

((stepframe < (Q1 - 1.5 * IQR)) | (stepframe > (Q3 + 1.5 * IQR))).sum()
Out[35]: 
Day                      0
Col1                     0
Col2                     0
col3                     0
Col4                     0
Step_Count            1179
dtype: int64

我只是想知道,我下一步要做什么,以便从 Dataframe 中删除所有离群值。
如果我用这个

def remove_outlier(df_in, col_name):
q1 = df_in[col_name].quantile(0.25)
q3 = df_in[col_name].quantile(0.75)
iqr = q3-q1 #Interquartile range
fence_low  = q1-1.5*iqr
fence_high = q3+1.5*iqr
df_out = df_in.loc[(df_in[col_name] > fence_low) & (df_in[col_name] < fence_high)]
return df_out

re_dat = remove_outlier(stepframe, stepframe.columns)

我收到此错误

ValueError: Cannot index with multidimensional key

在这一行

df_out = df_in.loc[(df_in[col_name] > fence_low) & (df_in[col_name] < fence_high)]
7tofc5zh

7tofc5zh1#

您可以用途:

np.random.seed(33454)
stepframe = pd.DataFrame({'a': np.random.randint(1, 200, 20), 
                          'b': np.random.randint(1, 200, 20),
                          'c': np.random.randint(1, 200, 20)})

stepframe[stepframe > 150] *= 10
print (stepframe)

Q1 = stepframe.quantile(0.25)
Q3 = stepframe.quantile(0.75)
IQR = Q3 - Q1

df = stepframe[~((stepframe < (Q1 - 1.5 * IQR)) |(stepframe > (Q3 + 1.5 * IQR))).any(axis=1)]

print (df)
      a    b     c
1   109   50   124
3   137   60  1990
4    19  138   100
5    86   83   143
6    55   23    58
7    78  145    18
8   132   39    65
9    37  146  1970
13   67  148  1880
15  124  102    21
16   93   61    56
17   84   21    25
19   34   52   126

详细信息

首先通过|创建chain boolean DataFrame

print (((stepframe < (Q1 - 1.5 * IQR)) | (stepframe > (Q3 + 1.5 * IQR))))
        a      b      c
0   False   True  False
1   False  False  False
2    True  False  False
3   False  False  False
4   False  False  False
5   False  False  False
6   False  False  False
7   False  False  False
8   False  False  False
9   False  False  False
10   True  False  False
11  False   True  False
12  False   True  False
13  False  False  False
14  False   True  False
15  False  False  False
16  False  False  False
17  False  False  False
18  False   True  False
19  False  False  False

然后使用DataFrame.any检查每行至少一个True,最后通过~反转布尔掩码:

print (~((stepframe < (Q1 - 1.5 * IQR)) | (stepframe > (Q3 + 1.5 * IQR))).any(axis=1))
0     False
1      True
2     False
3      True
4      True
5      True
6      True
7      True
8      True
9      True
10    False
11    False
12    False
13     True
14    False
15     True
16     True
17     True
18    False
19     True
dtype: bool

条件已更改的invert解决方案-<>=><=,按&进行“与”链接,最后按all进行过滤,以检查每行的所有True

print (((stepframe >= (Q1 - 1.5 * IQR)) & (stepframe <= (Q3 + 1.5 * IQR))).all(axis=1))
0     False
1      True
2     False
3      True
4      True
5      True
6      True
7      True
8      True
9      True
10    False
11    False
12    False
13     True
14    False
15     True
16     True
17     True
18    False
19     True
dtype: bool

df = stepframe[((stepframe >= (Q1 - 1.5 * IQR))& (stepframe <= (Q3 + 1.5 * IQR))).all(axis=1)]
biswetbf

biswetbf2#

您忘记在报价单(['col_name'])中填写列的名称。
正确答案是:

df_out = df_in.loc[(df_in['col_name'] > fence_low) & (df_in['col_name'] < fence_high)]
ig9co6j1

ig9co6j13#

在使用此函数之前,请确保您的DATAFRAME在“df”变量中,因为我以这种方式构建此函数。如果您有不同的DATAFRAME变量名称,请将“df”替换为您的DATAFRAME变量名称,就是这样。
为什么我构建冗长的函数??-〉因为我想要每一个信息,如异常值,异常值的索引,这样我就可以看到它是如何与较低和较高的围栏运作。

def outliers(data):
    Q1 = data.quantile(0.25)
    Q3 = data.quantile(0.75)
    IQR = Q3 - Q1

    Lower_fence = Q1 - (1.5*IQR)
    print(f"Lower fence is = {Lower_fence}")

    Higher_fence = Q3 + (1.5*IQR)
    print(f"Higher fence is = {Higher_fence}")
      
    #here i'm taking all Outliers and appending this in Variable "Outlier".
    Outlier =[]
    for i in data:
        if i < Lower_fence:
            Outlier.append(i)
            data.drop(data==i)
        elif i > Higher_fence:
            Outlier.append(i)

    #With the help of "index" function here we are getting all the indexes of Lower_fence and Higher_fence

    Index_Outlier = df[data < Lower_fence ].index  
    Index_Outlier = df[data > Higher_fence].index

    #Here we are converting all the "Outliers" and "Index_Outliers" into string just to see all the data in One line
    #If you do print(Outliers) or print(Outliers_index) you will get every element of data in New Line.

    print(f"\nOutliers = {', '.join([str(x) for x in Outlier])}")
    print(f"\nOutliers_INDEX = {', '.join([str(x) for x in Index_Outlier ])}")

    #here we are seeing before and after shape.

    print(f'\nBEFORE dropping Outlier we have rows = {df.shape[0]}, and columns = {df.shape[1]}')

    df.drop(Index_Outlier,inplace=True)

    print(f'AFTER dropping Outlier we have rows = {df.shape[0]}, and columns = {df.shape[1]}')

相关问题