用什么替换异常值?(超市成交数据)

数据挖掘 Python 熊猫 统计数据 离群值
2022-03-06 13:25:27

我有一个超市的交易数据集。假设平均支出为 50 美元。

我想获取每个客户的平均支出,并根据这 50 美元的平均支出对他们进行排名。

例如:

John Doe 的平均支出是总体平均支出的 150% = “金牌客户”。

Jane Doe 的平均支出是总体平均支出的 25% = “青铜”

等等等等

现在要计算超市的总体平均支出,我想去掉异常值。这是一家杂货店,但他们可能会时不时地出售一台电视机。所以有一些单笔交易可能是 600 美元以上。我想摆脱这些。

问题是,我用什么代替它们?

我寻找高于平均值 3 个标准差的交易。这些是我的异常值。

我不想用平均值/中位数替换它们。如果我删除他们更大的购买并用 50 美元代替他们,我可能会失去一些“黄金”客户。

我可以用 替换异常值mean + 3*std_dev吗?

我正在使用python,所以当前代码是:

# set threshold above which transaction will be labeled an outlier
# this is the average spend plus 3 times standard dev

value_threshold = (df['amount'].mean()+(df['amount'].std()*3))


# now replace any outlier with the value threshold. 
# this will ensure any big spenders stay big spenders so I can rank them accordingly

df['amount'] = np.where(df['amount']>value_threshold ,value_threshold ,df['amount'])

我的方法有意义还是违反了任何规则?

我应该使用中位数而不是四分位间距来查找异常值吗?

分配:

在此处输入图像描述

使用我上面的方法删除异常值后。请注意,我们在图表右侧的数据中仍然有大笔支出。(我的黄金客户)

在此处输入图像描述

奖金

在修复异常值之前,我的交易数据的箱线图。太可怕了:

在此处输入图像描述

2个回答

最简单的方法

首先是一种非常快速且可能实用的方法:只需删除它们而不替换它们!

从您的条形图中,您似乎有很多交易——几十万。删除几百个(我什至看不到超过 600 美元交易的条形图)而不替换它们并不意味着剩余的数据不可用。替换那些事务,例如使用分布的平均值,基本上是试图确保它们对模型没有任何显着影响;那么替换它们有什么意义呢?

看看你的频率图,我很想知道最终的大峰出现了什么。你能删除那些交易吗?

你可以试一试,继续建模,看看你是否得到了合理的结果——如果没有,回来进一步调查。


返回统计方法

使用 3 个标准差并不是一个坏方法——假设您的数据是正态分布的,这意味着您只删除了 0.3% 的数据问题可能是您的交易金额分布看起来并不呈正态分布 - 它看起来更像是一个beta 分布(橙色线):

来自维基百科的 beta 分布

因此,您可以尝试通过计算beta 分布的参数并使用这些参数而不是正态均值/标准差来删除分布之外的数据。

为此,请查看scipy.stats.beta,并注意您可能应该将事务规范化到范围内[0, 1.0](请参阅 Scikit-Learn 的StandardScaler)。这是一个关于了解您的 beta 发行版输出的线程。


估算

如果您简单地将异常值视为缺失数据,那么在这本著名的书中有一些关于填补数据中缺失的空白(也称为数据插补)的好主意和解释:统计学习要素 (pdf)1- 见第 9.6 节。

1作者:特雷弗·哈斯蒂、罗伯特·蒂布希拉尼、杰罗姆·弗里德曼

您可以使用以下任何一种方法来替换异常值

基于分位数的底线和封顶 在此技术中,我们将对较低的值进行底线(例如,第 10 个百分位),对较高的值进行封顶(例如,第 90 个百分点)。下面的代码行分别打印变量“数量”的第 10 个和第 90 个百分位数。这些值将用于基于分位数的地板和封顶。

print(df['amount'].quantile(0.10))
print(df['amount'].quantile(0.90))

或者

顶部编码意味着将分布的最大值限制在任意设定值。顶部编码变量是对高于上限的数据点进行审查的变量。通过实施顶级编码,异常值被限制在某个最大值,并且看起来像许多其他观察值。