如何使用带有IQR的pandas过滤器?

Qij*_*Liu 24 python data-processing pandas iqr

是否有内置的方法通过IQR对列进行过滤(即Q1-1.5IQR和Q3 + 1.5IQR之间的值)?另外,建议大熊猫中任何其他可能的广义过滤都将受到重视.

Rom*_*ain 34

据我所知,最简洁的符号似乎是由该query方法带来的.

# Some test data
np.random.seed(33454)
df = (
    # A standard distribution
    pd.DataFrame({'nb': np.random.randint(0, 100, 20)})
        # Adding some outliers
        .append(pd.DataFrame({'nb': np.random.randint(100, 200, 2)}))
        # Reseting the index
        .reset_index(drop=True)
    )

# Computing IQR
Q1 = df['nb'].quantile(0.25)
Q3 = df['nb'].quantile(0.75)
IQR = Q3 - Q1

# Filtering Values between Q1-1.5IQR and Q3+1.5IQR
filtered = df.query('(@Q1 - 1.5 * @IQR) <= nb <= (@Q3 + 1.5 * @IQR)')
Run Code Online (Sandbox Code Playgroud)

然后我们可以绘制结果以检查差异.我们观察到左侧框图中的异常值(183处的交叉)在过滤后的系列中不再出现.

# Ploting the result to check the difference
df.join(filtered, rsuffix='_filtered').boxplot()
Run Code Online (Sandbox Code Playgroud)

filterinf之前和之后的比较

由于这个答案,我写了一篇关于这个主题的帖子,你可以找到更多的信息.

  • 这个解决方案可以通过 `Q1, Q3 = df['nb'].quantile([.25, .75])` 变得毫无意义 (2认同)

MLe*_*ast 9

使用Series.between()的另一种方法:

iqr = df['col'][df['col'].between(df['col'].quantile(.25), df['col'].quantile(.75), inclusive=True)]
Run Code Online (Sandbox Code Playgroud)

抽出:

q1 = df['col'].quantile(.25)
q3 = df['col'].quantile(.75)
mask = d['col'].between(q1, q2, inclusive=True)
iqr = d.loc[mask, 'col']
Run Code Online (Sandbox Code Playgroud)

  • 需要明确的是,这将返回第 25 个百分位数和第 75 个百分位数之间的值(Q1 和 Q3)。它不会对 Q1-1.5IQR 和 Q3+1.5IQR 进行过滤。因此,如果您想使用 Q1-1.5IQR 和 Q3+1.5IQR 进行异常值分类:请使用此处的其他选项之一。 (9认同)

kd8*_*d88 6

这将使您的子集df位于column的IQR中column

def subset_by_iqr(df, column, whisker_width=1.5):
    """Remove outliers from a dataframe by column, including optional 
       whiskers, removing rows for which the column value are 
       less than Q1-1.5IQR or greater than Q3+1.5IQR.
    Args:
        df (`:obj:pd.DataFrame`): A pandas dataframe to subset
        column (str): Name of the column to calculate the subset from.
        whisker_width (float): Optional, loosen the IQR filter by a
                               factor of `whisker_width` * IQR.
    Returns:
        (`:obj:pd.DataFrame`): Filtered dataframe
    """
    # Calculate Q1, Q2 and IQR
    q1 = df[column].quantile(0.25)                 
    q3 = df[column].quantile(0.75)
    iqr = q3 - q1
    # Apply filter with respect to IQR, including optional whiskers
    filter = (df[column] >= q1 - whisker_width*iqr) & (df[column] <= q3 + whisker_width*iqr)
    return df.loc[filter]                                                     

# Example for whiskers = 1.5, as requested by the OP
df_filtered = subset_by_iqr(df, 'column_name', whisker_width=1.5)
Run Code Online (Sandbox Code Playgroud)


Nav*_*een 6

使用 找到第 1 个和第 3 个四分位数df.quantile,然后在数据帧上使用掩码。如果您想删除它们,请使用no_outliers并反转掩码中的条件以获取outliers.

Q1 = df.col.quantile(0.25)
Q3 = df.col.quantile(0.75)
IQR = Q3 - Q1
no_outliers = df.col[(Q1 - 1.5*IQR < df.BMI) &  (df.BMI < Q3 + 1.5*IQR)]
outliers = df.col[(Q1 - 1.5*IQR >= df.BMI) |  (df.BMI >= Q3 + 1.5*IQR)]
Run Code Online (Sandbox Code Playgroud)


dan*_*nek 5

另一种方法使用 Series.clip:

q = s.quantile([.25, .75])
s = s[~s.clip(*q).isin(q)]
Run Code Online (Sandbox Code Playgroud)

详细信息如下:

s = pd.Series(np.randon.randn(100))
q = s.quantile([.25, .75])  # calculate lower and upper bounds
s = s.clip(*q)  # assigns values outside boundary to boundary values
s = s[~s.isin(q)]  # take only observations within bounds
Run Code Online (Sandbox Code Playgroud)

使用它来过滤整个数据帧df很简单:

def iqr(df, colname, bounds = [.25, .75]):
    s = df[colname]
    q = s.quantile(bounds)
    return df[~s.clip(*q).isin(q)]
Run Code Online (Sandbox Code Playgroud)

注意:该方法不包括边界本身。