Numpy转变为正态分布

时间:2015-11-30 13:23:11

标签: python numpy normalization

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

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'并且'浮动'

编辑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)

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

我遇到了同样的问题。我的数据不像您的数据正常,因此我不得不将数据转换为正态分布。要将数据转换为普通数据,您应通过here等不同方法使用普通分数转换。您也可以使用these formulas。我编写了一个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 ]

通过Q-Q图可以看到,在进行此转换后,您的新数据是完全正常的:

from scipy import stats
import matplotlib.pyplot as plt

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