在python中使用Mann-Kendall处理大量数据

在python中使用Mann-Kendall处理大量数据,python,arrays,numpy,statistics,jupyter-notebook,Python,Arrays,Numpy,Statistics,Jupyter Notebook,我有一套46年的降雨量数据。它以46个numpy数组的形式出现,每个数组的形状分别为145、192,因此,在给定模型中,每年在每个纬度和经度坐标处都有不同的最大降雨量数据数组 我需要通过在46年中对每个坐标进行M-K测试(Mann-Kendall),创建tau值的全球地图 我还在学习python,所以我一直很难找到一种简单的方法来遍历所有数据,而不需要为每个坐标创建27840个新数组 到目前为止,我已经从这里了解了如何使用和使用定义: 编辑: 为了澄清并添加更多细节,我需要对每个坐标执行测试,而

我有一套46年的降雨量数据。它以46个numpy数组的形式出现,每个数组的形状分别为
145、192
,因此,在给定模型中,每年在每个纬度和经度坐标处都有不同的最大降雨量数据数组

我需要通过在46年中对每个坐标进行M-K测试(Mann-Kendall),创建tau值的全球地图

我还在学习python,所以我一直很难找到一种简单的方法来遍历所有数据,而不需要为每个坐标创建27840个新数组

到目前为止,我已经从这里了解了如何使用和使用定义:

编辑:

为了澄清并添加更多细节,我需要对每个坐标执行测试,而不仅仅是对每个文件单独执行测试。例如,对于第一个M-K测试,我想要x=46,我想要y=data1[0,0],data2[0,0],data3[0,0]…data46[0,0]。然后对每个阵列中的每个坐标重复此过程。总的来说,M-K测试将进行27840次,给我留下27840个tau值,然后我可以在全局地图上绘制

编辑2:

我现在遇到了另一个问题。根据建议的代码,我有以下内容: 范围(145)内的i的
:
对于范围(192)内的j:
out[i,j]=mk_检验(yrmax[:,i,j],α=0.05)
打印输出

我使用
numpy.stack
将所有46个数组堆叠成一个数组(yrmax),形状:
(46L,145L,192L)
我已经测试过了,如果我将代码从out[I,j]更改为just out,它会正确计算p和tau。但是,这样做会弄乱for循环,因此它只获取最后一个坐标的结果,而不是所有坐标的结果。如果我让代码保持上面的状态,我会得到错误:
TypeError:list索引必须是整数,而不是tuple

我的第一个猜测是,它与mk_测试以及如何在定义中返回信息有关。因此,我尝试通过修改上面链接中的代码来改变数据的返回方式,但我不断收到与元组相关的错误。所以现在我不确定哪里出了问题以及如何修复它

编辑3:


我想我应该补充一点澄清。我已经修改了链接中的定义,因此它只返回创建贴图所需的两个数值p和z

根据您的情况,制作阵列可能是最简单的

你不会真的需要一次将它们全部存储在内存中(并不是说这听起来像是一个可怕的数据量)。像这样的东西一次只需处理一个“复制”的坐标趋势:

SIZE = (145,192)
year_matrices = load_years() # list of one 145x192 arrays per year
result_matrix = numpy.zeros(SIZE)
for x in range(SIZE[0]):
    for y in range(SIZE[1]):
        coord_trend = map(lambda d: d[x][y], year_matrices)
        result_matrix[x][y] = analyze_trend(coord_trend)
print result_matrix
现在,如果您真的想避免实际复制数据,那么这样的事情可以帮助您

下面是一个具体的例子,说明Python的“zip”如何处理像您这样的数据(尽管好像您每年都使用
ndarray.flant
):

上面的示例仍然复制数据(并且一次复制所有数据,而不是一次复制一个坐标!),但希望能够显示出发生了什么

现在,如果将
zip
替换为
itertools.izip
并将
map
替换为
itertools.map
,则无需复制-itertools包装原始数组并跟踪从内部获取值的位置

不过,这里有一个陷阱:利用itertools只按顺序(即通过迭代)访问数据。在您的情况下,看起来处的代码可能与此不兼容。(我还没有检查过算法本身,看它是否可行。)


另外请注意,在这个示例中,我忽略了numpy ndarray的内容,只显示了平面坐标数组。看起来numpy有自己的一些选项来处理这个问题,而不是itertools,例如说“对数组进行转置并不能生成副本”。您的问题有些笼统,因此我尝试给出一些关于如何在Python中处理较大数据的一般提示。

我认为这并不像您想象的那么大。根据您的描述,听起来您实际上并不想要scipy kendalltau,而是想要您发布的存储库中的函数。下面是我设置的一个小示例:

from time import time

import numpy as np
from mk_test import mk_test

data = np.array([np.random.rand(145, 192) for _ in range(46)])
mk_res = np.empty((145, 192), dtype=object)
start = time()
for i in range(145):
    for j in range(192):
        out[i, j] = mk_test(data[:, i, j], alpha=0.05)
print(f'Elapsed Time: {time() - start} s')

Elapsed Time: 35.21990394592285 s
我的系统是MacBook Pro 2.7 GHz Intel Core I7,带有16 GB Ram,因此没有什么特别之处

mk_res数组(形状145、192)中的每个条目对应于您的一个坐标点,并包含如下条目:

array(['no trend', 'False', '0.894546014835', '0.132554125342'], dtype='<U14')

array(['no trend'、'False'、'0.894546014835'、'0.132554125342'],dtype='感谢提供的答案和一些工作,我能够制定出一个解决方案,我将在这里为需要使用Mann-Kendall测试进行数据分析的任何其他人提供

我需要做的第一件事是将我拥有的原始阵列展平为1D阵列。我知道可能有一种更简单的方法可以做到这一点,但我最终使用了以下基于Grr建议使用的代码的代码

`x = 46
out1 = np.empty(x)
out = np.empty((0))
for i in range(146):
    for j in range(193):
        out1 = yrmax[:,i,j]
        out = np.append(out, out1, axis=0) `
然后,我对结果数组(out)进行了如下重塑:

out2=np.重塑(out,(27840,46))

我这样做是为了让我的数据采用与scipy.stats兼容的格式。kendalltau
27840是我在地图上每个坐标的值总数(即,它只有145*192),46是数据跨越的年数

然后,我使用我从Grr的代码中修改的以下循环来查找Kendall tau,以及46年期间每个纬度和经度的p值

`x = range(46)
 y = np.zeros((0))
for j in range(27840):
    b = sc.stats.kendalltau(x,out2[j,:])
    y = np.append(y, b, axis=0)`
最后,我对数据进行了一次整形,如图所示:
newdata=np。整形(y,(145192,2))
因此最终数组的格式适合用于创建tau和p值的全局映射


谢谢大家的帮助!

我不太懂这里的科学,但你可能只需要用硬件来解决这个问题。也就是说,有很多方法可以避免出现问题
`x = range(46)
 y = np.zeros((0))
for j in range(27840):
    b = sc.stats.kendalltau(x,out2[j,:])
    y = np.append(y, b, axis=0)`