【问题标题】:Taking np.average while ignoring NaN's?在忽略 NaN 的同时采用 np.average?
【发布时间】:2016-06-15 22:49:18
【问题描述】:

我有一个形状 (64,17) 对应于时间和纬度的矩阵。我想采用加权纬度平均值,我知道 np.average 可以这样做,因为与我用来平均经度的 np.nanmean 不同,可以在参数中使用权重。但是,np.average 不会像 np.nanmean 那样忽略 NaN,因此我每行的前 5 个条目都包含在纬度平均中,并使整个时间序列充满 NaN。

有没有一种方法可以在不包含 NaN 的情况下进行加权平均?

file = Dataset("sst_aso_1951-2014latlon_seasavgs.nc")
sst = file.variables['sst']
lat = file.variables['lat']

sst_filt = np.asarray(sst)
missing_values_indices = sst_filt < -8000000   #missing values have value -infinity
sst_filt[missing_values_indices] = np.nan      #all missing values set to NaN

weights = np.cos(np.deg2rad(lat))
sst_zonalavg = np.nanmean(sst_filt, axis=2)
print sst_zonalavg[0,:]
sst_ts = np.average(sst_zonalavg, axis=1, weights=weights)
print sst_ts[:]

输出:

[ nan nan nan nan nan
 27.08499908 27.33333397 28.1457119 28.32899857 28.34454346
 28.27285767 28.18571472 28.10199928 28.10812378 28.03411865
 28.06411552 28.16529465]

[ nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan]

【问题讨论】:

    标签: python numpy latitude-longitude weighted-average


    【解决方案1】:

    你可以像这样创建一个掩码数组:

    data = np.array([[1,2,3], [4,5,np.NaN], [np.NaN,6,np.NaN], [0,0,0]])
    masked_data = np.ma.masked_array(data, np.isnan(data))
    # calculate your weighted average here instead
    weights = [1, 1, 1]
    average = np.ma.average(masked_data, axis=1, weights=weights)
    # this gives you the result
    result = average.filled(np.nan)
    print(result)
    

    这个输出:

    [ 2.   4.5  6.   0. ]
    

    【讨论】:

    • 我提到我不能使用 np.nanmean 因为它的参数没有权重。我正在尝试做一个加权平均。
    • 我已经更新了答案以使用掩码数组和np.mean
    • 我正准备在原始帖子中编辑一个提及,因为我正在做一个时间序列,从数据中删除 NaN 也是一种选择,但你打败了我!
    • 编辑:实际上,这仍然不太有效。我仍然需要取加权平均值,而 np.mean 不这样做。当我改用 np.average 时,它​​仍然输出 NaN。
    • 我已经更新了我的答案,它现在应该可以工作了,你需要使用 np.ma.average 来屏蔽数组。请注意.ma
    【解决方案2】:

    您可以简单地将输入数组与weights 相乘并沿指定轴求和,而忽略NaNsnp.nansum。因此,对于您的情况,假设 weights 将与输入数组 axis = 1 一起使用 sst_filt,总和将是 -

    np.nansum(sst_filt*weights,axis=1)
    

    在平均时考虑到 NaN,我们最终会得到:

    def nanaverage(A,weights,axis):
        return np.nansum(A*weights,axis=axis)/((~np.isnan(A))*weights).sum(axis=axis)
    

    示例运行 -

    In [200]: sst_filt  # 2D array case
    Out[200]: 
    array([[  0.,   1.],
           [ nan,   3.],
           [  4.,   5.]])
    
    In [201]: weights
    Out[201]: array([ 0.25,  0.75])
    
    In [202]: nanaverage(sst_filt,weights=weights,axis=1)
    Out[202]: array([0.75, 3.  , 4.75])
    

    【讨论】:

    • 如果两个数组都是 2D 并且都有一些 NaN,你的解决方案会起作用吗?
    【解决方案3】:

    我可能只选择数组中不是 NaN 的部分,然后也使用这些索引来选择权重。

    例如:

    import numpy as np
    data = np.random.rand(10)
    weights = np.random.rand(10)
    data[[2, 4, 8]] = np.nan
    
    print data
    # [ 0.32849204,  0.90310062,         nan,  0.58580299,         nan,
    #    0.934721  ,  0.44412978,  0.78804409,         nan,  0.24942098]
    
    ii = ~np.isnan(data)
    print ii
    # [ True  True False  True False  True  True  True False  True]
    
    result = np.average(data[ii], weights = weights[ii])
    print result
    # .6470319
    

    编辑:我意识到这不适用于二维数组。在这种情况下,我可能只是将 NaN 的值和权重设置为零。这会产生相同的结果,就好像这些指数没有包含在计算中一样。

    在运行 np.average 之前:

    data[np.isnan(data)] = 0;
    weights[np.isnan(data)] = 0;
    result = np.average(data, weights=weights)
    

    如果您想跟踪哪些索引是 NaN,请创建副本。

    【讨论】:

    • 为什么您的原始解决方案不适用于二维数组?
    【解决方案4】:

    @deto

    第一行删除了所有的 nan,这将导致第二行的结果不正确。

    data[np.isnan(data)] = 0;
    weights[np.isnan(data)] = 0;
    result = np.average(data, weights=weights)
    

    在运行第一行之前应该复制一份

    data_copy = copy.deepcopy(data)
    data[np.isnan(data_copy)] = 0;
    weights[np.isnan(data_copy)] = 0;
    result = np.average(data, weights=weights)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-03
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 2021-11-15
      • 2014-11-26
      • 2018-07-05
      • 2019-09-24
      相关资源
      最近更新 更多