web-dev-qa-db-ja.com

IQRを使用してDataFrameから外れ値を削除する方法

列数が多い(約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

データフレームからすべての外れ値が削除されるように、次に何をするかを知りたかっただけです。

これを使用している場合

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)]
4

以下を使用できます。

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

詳細

まず、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 を使用して、行ごとに少なくとも1つの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ソリューション-<から>=および>から<=&でANDおよび最後のフィルターでチェーン- all 行ごとにすべてのTruesをチェックする

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)]
3
jezrael