为数据库设置阈值:如何移除散点图中的异常值
仅通过散点图能否确定异常值移除方法?
可以,从你提供的含异常值的散点图能看到,正常数据呈现明显的线性相关特征——通话时长(total_day_minutes)和费用(total_day_charge)理论上是按固定费率计费的,正常点会集中在一条直线附近,偏离这条直线的点就是干扰分析的异常值。基于这个规律,能直接给出以下几种移除方法:
方法1:基于费率范围过滤
正常情况下,total_day_charge / total_day_minutes应该等于固定通话费率(比如常见的0.1美元/分钟这类),你可以通过观察散点图的线性斜率确定合理费率范围,再筛选出符合该范围的数据:
# 假设从图中判断合理费率在0.09~0.11之间,可根据实际数据调整 valid_rate_mask = (df['total_day_charge'] / df['total_day_minutes']).between(0.09, 0.11) # 过滤异常值后的数据集 filtered_df = df[valid_rate_mask]
方法2:基于线性拟合残差过滤
用线性回归拟合正常数据的线性关系,计算每个点的预测残差(实际值与模型预测值的差值),移除残差过大的点:
from sklearn.linear_model import LinearRegression # 提取目标列数据 X = df[['total_day_minutes']].values y = df['total_day_charge'].values # 拟合线性模型 model = LinearRegression() model.fit(X, y) y_pred = model.predict(X) # 计算残差并设置过滤阈值(均值+2倍标准差是常用的异常值判定标准) residuals = abs(y - y_pred) threshold = residuals.mean() + 2 * residuals.std() # 过滤异常值 filtered_df = df[residuals < threshold]
方法3:坐标范围+线性关系双重过滤
结合你绘图时设置的x/y轴范围,同时加入线性费率约束,进一步精准筛选:
# 先限定基础数值范围,再过滤符合费率要求的点 range_mask = (df['total_day_minutes'].between(0, 500)) & (df['total_day_charge'].between(0, 60)) rate_mask = (df['total_day_charge'] / df['total_day_minutes']).between(0.09, 0.11) filtered_df = df[range_mask & rate_mask]
补充说明
这些方法的核心依据都是散点图呈现的线性相关性——通话时长与费用的业务逻辑是线性计费,偏离这个关系的点必然是异常(比如数据录入错误、计费系统bug等)。如果需要更精准的阈值,可以先过滤掉明显偏离的点,再重新计算费率或残差阈值做二次过滤。
你提供的原始绘图代码整理如下:
fig, axs = plt.subplots(nrows=1, ncols=3, figsize=[18, 6]) # 定义包含3个子图的画布(日、夜、晚) df.plot(kind='scatter', x='total_day_minutes', y='total_day_charge', ax=axs[0], xlim=(0,500), ylim=(0,60)); # 绘制日间数据散点图 df.plot(kind='scatter', x='total_eve_minutes', y='total_eve_charge', ax=axs[1], xlim=(0,500), ylim=(0,60)); # 绘制晚间数据散点图 df.plot(kind='scatter', x='total_night_minutes', y='total_night_charge', ax=axs[2], xlim=(0,500), ylim=(0,60)); # 绘制夜间数据散点图
内容的提问来源于stack exchange,提问作者Денис Жгута
相关产品推荐
相关产品推荐

