Python 熊猫数据帧的多重分布正态性检验与转换

Python 熊猫数据帧的多重分布正态性检验与转换,python,pandas,statistics,normal-distribution,Python,Pandas,Statistics,Normal Distribution,情况: 让我们考虑一个庞大的零售网络(数百个产品和数以千计的商店)简化如下: 一号店,二号店 产品A、产品B、产品C 我试图找出销售数据中的异常情况,以了解哪些商店做得很好,哪些做得很差 我的第一个想法是计算销售的平均值和标准差,并将所有超出3个标准差范围的情况(正态分布中约5%的情况)限定为异常 然而,当目视检查分布时,我注意到它们不是正态分布。考虑到许多可能的商店/产品组合,我无法手动检查和转换它们 方法: 在Python中,首先使用D'Agostino和Pearson的测试测试每个商店/

情况:

让我们考虑一个庞大的零售网络(数百个产品和数以千计的商店)简化如下:

一号店,二号店

产品A、产品B、产品C

我试图找出销售数据中的异常情况,以了解哪些商店做得很好,哪些做得很差

我的第一个想法是计算销售的平均值和标准差,并将所有超出3个标准差范围的情况(正态分布中约5%的情况)限定为异常

然而,当目视检查分布时,我注意到它们不是正态分布。考虑到许多可能的商店/产品组合,我无法手动检查和转换它们


方法:

在Python中,首先使用D'Agostino和Pearson的测试测试每个商店/产品销售的分布是否正常。我读到Shapiro-Wilk测试在较小的数据集上效果更好,所以我排除了它

然后,我们过滤数据帧,只保留未通过正态性测试的组合,并对其进行转换

  • 我们可以使用诸如偏度和峰度之类的信息来自动决定使用什么(log、sqrt等)
  • 或者使用不同的变换并再次测试法线,以了解哪些变换有效
一旦所有的组合都是正态分布,我就可以继续我的分析,把3个标准偏差之外的所有东西都归类为异常

目前,我已经找到了一些运行正常性测试的代码:

# D'Agostino and Pearson's Test
from numpy.random import seed
from numpy.random import randn
from scipy.stats import normaltest
# seed the random number generator
seed(1)
# generate univariate observations
data = 5 * randn(100) + 50
# normality test
stat, p = normaltest(data)
print('Statistics=%.3f, p=%.3f' % (stat, p))
# interpret
alpha = 0.05
if p > alpha:
    print('Sample looks Gaussian (fail to reject H0)')
else:
    print('Sample does not look Gaussian (reject H0)')
然而,我不知道如何在熊猫数据框中运行它,自动过滤数千个商店/产品组合

我有一种预感,我可以使用itertool创建一个具有所有唯一组合的数据框,然后使用此参考数据框作为过滤器,以一个唯一的函数跨整个销售数据框运行测试,但老实说,这远远超出了我目前的技能

from itertools import product
pd.DataFrame(list(product(Store, Product)), columns=['Store', 'Product'])

  Store  Product
0  1      A
1  1      B
2  1      C
3  2      A
4  2      B
5  2      C

我可以征求一些想法或线索来完成这项任务吗?也许我甚至试图重新发明轮子,类似的东西已经存在,但我什么也没发现。您认为总体方法如何

无论如何,我很乐意阅读你的意见

多谢各位

更新:

from scipy.stats import normaltest
alpha = 0.05
test = df.groupby(['Store', 'Product'])['Sales'].apply(normaltest)
normality = test.apply(pd.Series, index=["stat", "p"])
normality['normal'] = np.where(normality['p']>alpha, 1,0)

您可以使用
DataFrame.groupby
为每个[Store x Product]组合将您的数据帧分离为一个子集,然后您可以
将您的函数应用于这些子集。例如
df.groupby(['Store','Product'])['Sales'].应用(我的正常性测试)
谢谢Alolz。它就像一个符咒。在原始帖子中作为更新发布。