我有一组数据。我查看它是否正常分发:
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)
答案 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()