NumPy“空片段的平均数”警告。

6

更新(真正的错误)

我误认为错误来自于其他地方。这是我的整个函数(如果有些行不清楚和混乱,很抱歉...)

def removeLines(input,CRVAL1,CDELT1): #Masks out the Balmer lines from the spectrum
    #Numbers 4060, 4150, 4300, 4375, 4800, and 4950 obtained from fit_RVs.pro.
    #Other numbers obtained from the Balmer absorption series lines
    
    for i in range(0,len(lineWindows),2):
        left = toIndex(lineWindows[i],CRVAL1,CDELT1)
        right = toIndex(lineWindows[i+1],CRVAL1,CDELT1)
        
        print "left = ", left
        print "right = ", right
        print "20 from right =\n", input[right:right+20]
        print "mean of 20 = ", numpy.mean(input[right:right+20])
        
        #Find the averages on the left and right sides
        left_avg = numpy.mean(input[left-20:left])
        right_avg = numpy.mean(input[right:right+20])   #<--- NOT here
        
        print "right_avg = ", right_avg
        
        #Find the slope between the averages
        slope = (left_avg - right_avg)/(left - right)
        
        #Find the y-intercept of the line conjoining the averages
        bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
        
        for j in range(left,right):     #Redefine the data to follow the line conjoining
            input[j] = slope*j + bval   #the sides of the peaks

    left = int(input[0])
    left_avg = int(input[0])
    right = toIndex(lineWindows[0],CRVAL1,CDELT1)
    right_avg = numpy.mean(input[right:right+20])   #<---- THIS IS WHERE IT IS!
    slope = (left_avg - right_avg)/(left - right)
    bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
    
    for i in range(left, right):
        input[i] = slope*i + bval
    return input

我已经调查了这个问题,并找到了答案,下面是发布的答案(不在此帖子中)。


错误(愚蠢的虚假错误)

#left  = An index in the data (on the 'left' side)
#right = An index in the data (on the 'right' side)
#input = The data array

print "left = ", left
print "right = ", right
print "20 from right =\n", input[right:right+20]
print "mean of 20 = ", numpy.mean(input[right:right+20])

#Find the averages on the left and right sides
left_avg = numpy.mean(input[left-20:left])
right_avg = numpy.mean(input[right:right+20])

生成输出

left =  1333
right =  1490
20 from right =
[ 0.14138737  0.14085886  0.14038289  0.14045525  0.14078836  0.14083192
  0.14072289  0.14082283  0.14058594  0.13977806  0.13955595  0.13998236
  0.1400764   0.1399636   0.14025062  0.14074247  0.14094831  0.14078569
  0.14001536  0.13895717]
mean of 20 =  0.140395
Traceback (most recent call last):
...
  File "getRVs.py", line 201, in removeLines
    right_avg = numpy.mean(input[right:right+20])
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\fromnumeric.py", line 2735, in mean
    out=out, keepdims=keepdims)
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\_methods.py", line 59, in _mean
    warnings.warn("Mean of empty slice.", RuntimeWarning)
RuntimeWarning: Mean of empty slice.

似乎当我打印numpy.mean时,它可以正常运行,但是当我将其赋给一个值时,结果不同。非常感谢您提供的任何反馈。谢谢您抽出时间阅读我的问题。

简要解释

简而言之,我正在编写一段代码来处理科学数据,其中一部分代码涉及对大约20个值取平均。

#left  = An index in the data (on the 'left' side)
#right = An index in the data (on the 'right' side)
#input = The data array

#Find the averages on the left and right sides
left_avg = numpy.mean(input[left-20:left])
right_avg = numpy.mean(input[right:right+20])

这段代码返回一个numpy的“空切片的平均值”警告,并且会在输出中烦人地打印出来!我决定尝试追踪警告的来源,例如在这里看到的那样,所以我放置了:

import warnings
warnings.simplefilter("error")

在我的代码顶部,然后返回以下片段Traceback:
  File "getRVs.py", line 201, in removeLines
    right_avg = numpy.mean(input[right:right+20])
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\fromnumeric.py", line 2735, in mean
    out=out, keepdims=keepdims)
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\_methods.py", line 59, in _mean
    warnings.warn("Mean of empty slice.", RuntimeWarning)
RuntimeWarning: Mean of empty slice.

我省略了大约2/3的Traceback,因为它经过了约5个难以解释的函数,这些函数不会影响数据的可读性或大小。
所以我决定打印整个操作,看看right_avg是否真的尝试对一个空切片进行numpy.mean...就在那时,事情变得非常奇怪。

1
错误提示是说第二次调用 numpy.mean(input[right:right+20]) 时,input[right:right+20] 是空的。在第一次和第二次调用之间必须有代码更改了 input 的值。 - unutbu
您说得对,input的值正在被更改,但是在调用之前甚至打印相同代码时没有错误。您认为这与我如何分配left_avg有关吗? - boof
你是对的!同一个函数后面有一部分代码处理 right_avg!我已经更新了主线程,以避免浪费大家的时间。真尴尬... - boof
检查 right = toIndex(lineWindows[0],CRVAL1,CDELT1) 的值。如果它太大,那么切片 input[right:right+20] 可能为空。 - unutbu
可能是这个问题的重复:mean、nanmean和warning: Mean of empty slice - Michael Currie
2个回答

1
我无法再现您的错误。您是否使用了最新版本的numpy? 然而,您可以使用关键字 ignore 来抑制警告(请参见https://docs.python.org/2/library/warnings.html#temporarily-suppressing-warnings)。 此错误通常意味着将一个空列表传递给函数。
>>> a = []

>>> import numpy
>>> numpy.mean(a)
/shahlab/pipelines/apps_centos6/Python-2.7.10/lib/python2.7/site-packages/numpy/core/_methods.py:59: RuntimeWarning: Mean of empty slice.
  warnings.warn("Mean of empty slice.", RuntimeWarning)
/shahlab/pipelines/apps_centos6/Python-2.7.10/lib/python2.7/site-packages/numpy/core/_methods.py:71: RuntimeWarning: invalid value encountered in double_scalars
  ret = ret.dtype.type(ret / rcount)
nan
>>> print numpy.mean(a)
nan

>>> import warnings
>>> warnings.simplefilter("ignore")
>>> numpy.mean(a)
nan

>>> a=[ 0.14138737, 0.14085886, 0.14038289, 0.14045525, 0.14078836, 0.14083192, 0.14072289, 0.14082283, 0.14058594, 0.13977806, 0.13955595, 0.13998236, 0.1400764,  0.1399636,  0.14025062, 0.14074247, 0.14094831, 0.14078569, 0.14001536, 0.13895717]
>>> numpy.mean(a)
0.140394615
>>> x = numpy.mean(a)
>>> print x
0.140394615
>>> numpy.__version__
'1.9.2'

希望能有所帮助。

谢谢你的回答!一开始我尝试抑制警告,但是我的脑海里突然想起了一个小红旗。我在处理_科学_数据,这意味着如果我的代码因为某种未知原因处理空列表,那将是一个大问题。当我去检查它时,列表并不像numpy告诉我的那样为空!所以现在我正在努力弄清楚为什么numpy会这样做。 我还使用的是numpy版本1.9.2。 - boof
很奇怪,代码没有改变“input”列表。能否发布可以重现此错误的代码(也许使用较小的输入列表)?我将尝试使用一些虚拟数据来查看是否会出现相同的错误。 - Diljot
我刚刚更新了主贴。我犯了一个错误,把错误的代码行标识为错误。现在我正在看的东西更有意义,可以解释警告的原因。对不起! - boof

1
我误认为错误代码所在的行。我需要在代码中编写特定情况的代码,即考虑数据中心点周围的窗口(leftright边)过于靠近数据数组的边缘
def removeLines(input,CRVAL1,CDELT1): #Masks out the Balmer lines from the spectrum
    
    for i in range(0,len(lineWindows),2):
        left = toIndex(lineWindows[i],CRVAL1,CDELT1)
        right = toIndex(lineWindows[i+1],CRVAL1,CDELT1)
        
        #Find the averages on the left and right sides
        left_avg = numpy.mean(input[left-20:left])
        right_avg = numpy.mean(input[right:right+20])
        
        #Find the slope between the averages
        slope = (left_avg - right_avg)/(left - right)
        
        #Find the y-intercept of the line conjoining the averages
        bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
        
        for j in range(left,right):     #Redefine the data to follow the line conjoining
            input[j] = slope*j + bval   #the sides of the peaks

    left = 0
    left_avg = int(input[0])
    
    if toIndex(lineWindows[0],CRVAL1,CDELT1) < 0: right = 0
    else: right = toIndex(lineWindows[0],CRVAL1,CDELT1)

    right_avg = numpy.mean(input[right:right+20])
    slope = (left_avg - right_avg)/(left - right)
    bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
    
    for i in range(left, right):
        input[i] = slope*i + bval
    return input

只需更改此处内容

right = toIndex(lineWindows[0],CRVAL1,CDELT1)    #Error occurs where right = -10
right_avg = numpy.mean(input[right:right+20])    #Index of -10? Yeah, right.

到这里

if toIndex(lineWindows[0],CRVAL1,CDELT1) < 0: right = 0    #Index 0, much better!
else: right = toIndex(lineWindows[0],CRVAL1,CDELT1)    #Leave it alone if it isn't a problem.

right_avg = numpy.mean(input[right:right+20])

另外,我关于left = int(input[0])的错误已被更正为left = 0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接