繁体   English   中英

Numpy转变为正态分布

[英]Numpy transformation to normal distribution

我有一系列数据。 我查看它是否正常分发:

import sys
import scipy
from scipy import stats
from scipy.stats import mstats
from scipy.stats import normaltest

Data = []
for line in open(sys.argv[1]):
    line = line.strip()
    Data.append(float(line))
print scipy.stats.normaltest(Data)

产量为:(36.444648754208075,1.2193968690198398e-08)

然后,我写了一个小脚本来规范化数据:

import sys
import numpy as np
fileopen = open(sys.argv[1])
UntransformedArray = []
for line in fileopen:
    line = float(line.strip())
    UntransformedArray.append(line)
TransformedArray = (UntransformedArray - np.mean(UntransformedArray)/np.std(UntransformedArray))
NewList = TransformedArray.tolist()
for i in NewList:
    print i

然后我使用第一个脚本再次检查了正常性,输出是(36.444648754209595,1.2193968690189117e-08)。

...与之前的分数相同,而不是正常分布。

是我的一个脚本错了吗?

另外,我应该提到我的数据的平均值是0.056,数字的范围从0.014到0.171(85个观测值),我不确定数字是如此之小的事实。

未转换和转换数据的样本:

未转换:

0.055
0.074
0.049
0.067
0.038
0.037
0.045
0.041

转化数据:

-2.13696814254
-2.11796814254
-2.14296814254
-2.12496814254
-2.15396814254
-2.15496814254
-2.14696814254

编辑1:

当我稍微编辑代码以解释括号在错误的位置时:

TransformedMean = (UntransformedArray - np.mean(UntransformedArray))
TransformedArray = (TransformedMean/np.std(UntransformedArray))
NewList = TransformedArray.tolist()
for i in NewList:
    print i

输出我得到它不同:

例:

-0.0385683544143
0.705333390576
-0.273484694937
0.431264326632
-0.704164652563
-0.743317375984

但是,当我检查正常时:(36.444648754241328,1.2193968689995659e-08)

它仍然没有正常分布(并且仍然与其他时间完全相同)?

编辑2:

然后我尝试了另一种规范化数据的方法:

import sys
import scipy
from scipy import stats
from scipy.stats import boxcox

Data = [(float(line.strip())) for line in open(sys.argv[1])]
scipy.stats.boxcox(Data)

我收到错误:TypeError:**或pow()不支持的操作数类型:'list'和'float'

编辑3:由于用户的评论,问题在于理解标准化值与标准化分布的区别。

编辑代码:

import sys
import numpy as np

fileopen = open(sys.argv[1])
UntransformedArray = []
for line in fileopen:
    line = float(line.strip())
    UntransformedArray.append(line)

List1 =  np.log(UntransformedArray) 
for i in List1:
    print i

检查标准化:(4.0435072214905938,0.13242304287973003)

(在这种情况下,取决于数据的偏差)。

编辑4:或使用BoxCox转换:

import sys
import scipy
from scipy import stats
from scipy.stats import boxcox
import numpy as np

Data = []
for line in open(sys.argv[1]):
    line = line.strip()
    Data.append(float(line))

data = scipy.stats.boxcox(np.array(Data))
for i in data[0]:
    print i

检查是否正常化:(2.9085877478631956,0.23356523218452238)

正如预期的那样,减去均值和重新缩放到单位方差不会改变分布的形状。 normaltest在两种情况下都正确返回相同的输出,告诉您数据正常分布。

我同意托马斯的观点。 但更确切地说:您正在标准化阵列的分布! 这不会改变分布的形状! 您可能希望使用numpy.histogram()函数来获得分布的印象!

我认为你已经成为“正常化”令人困惑的双重用法的牺牲品。 一方面,规范化用于描述变量的标准化(以相同的比例获取变量 - 这就是你所做的)。 另一方面,归一化用于描述改变概率分布形状的尝试(scipy.stats.normaltest()用于检查这种分布的形状)。 尝试更正常地分发的一个简单策略是使用日志转换。 numpy.log()可能会在这里做到这一点,但前提是原始分布不是太偏斜。

我遇到了同样的问题。 我的数据与您的数据不正常,我不得不将数据转换为正态分布。 为了您的数据转换为正常的,你应该使用正常的分数通过不同的方法,因为它描述的变换一样在这里 您也可以使用这些公式 我编写了一个python代码,用于将元素列表更改为正态分布,如下所示:

X = [0.055, 0.074, 0.049, 0.067, 0.038, 0.037, 0.045, 0.041]

from scipy.stats import rankdata, norm

newX = norm.ppf(rankdata(x)/(len(x) + 1))
print(newX)

output:
[ 0.4307273   1.22064035  0.1397103   0.76470967 -0.76470967 -1.22064035
-0.1397103  -0.4307273 ]

通过QQ图可以看到,您可以看到此转换后您的新数据完全正常:

from scipy import stats
import matplotlib.pyplot as plt

ax4 = plt.subplot(111)
res = stats.probplot(newX, plot=plt)
plt.show()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM