Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 动态定义函数的编程概念_Python_Dynamic Programming_Python Xarray - Fatal编程技术网

Python 动态定义函数的编程概念

Python 动态定义函数的编程概念,python,dynamic-programming,python-xarray,Python,Dynamic Programming,Python Xarray,我的问题是,我计算了一个模型和一个参考数据集的不同评估度量——数据集用于三维(x,y,t)和netcdf数据。评估措施必须针对四种不同类型的时间聚集进行处理:无聚集、整个期间的聚集、重新采样的聚集(每月)和分组聚集(小时垂直时间、月垂直时间) 我选择PythonXarray作为工作平台,因为它们在netcdf处理方面非常灵活 从easy score BIAS开始,我有以下代码: def BIAS_temporal(self,varns_result=None,aggregtime=None,di

我的问题是,我计算了一个模型和一个参考数据集的不同评估度量——数据集用于三维(x,y,t)和netcdf数据。评估措施必须针对四种不同类型的时间聚集进行处理:无聚集、整个期间的聚集、重新采样的聚集(每月)和分组聚集(小时垂直时间、月垂直时间)

我选择PythonXarray作为工作平台,因为它们在netcdf处理方面非常灵活

从easy score BIAS开始,我有以下代码:

def BIAS_temporal(self,varns_result=None,aggregtime=None,dim_time=None):
    """ Compute the BIAS/ME for a timeseries -> e.g. R^3 --> R^2:
        BIAS(x,y) = SUM_{dim_t} ( MOD(x,y,dim_t) - OBS(x,y,dim_t) ) """
    def bias(x):
        return ( x[namex] - x[namey] )
    def biasmean(x):
        return ( x[namex] - x[namey] ).mean(dim=coordtime)
    #
    endresult = xarray.Dataset()
    for varnsproof,varnsref,varnsres in zip(self.varns_proof,self.varns_ref,varns_result):
        # rename the data variables and combine both datasets for evaluation
        namex=varnsres+"_x"; namey=varnsres+"_y"
        self.DSref.rename({varnsref : namey },inplace=True)
        self.DSproof.rename({varnsproof : namex },inplace=True)
        DScomb = xarray.merge([self.DSref,self.DSproof])
        coordtime     = self.MetricCalcProg.ListDimsToXarray(dim_time[varnsref])     #extract the name of time coordinate
        #
        if aggregtime == 'fullperiod':
            DSnew = biasmean(DScomb).to_dataset(name = varnsres)
            ...
        elif aggregtime == '-':
            DSnew = bias(DScomb).to_dataset(name = varnsres)
        elif "overperiod" in aggregtime:
            grpby_method=self.MetricCalcProg.ConvertAggregKey2Groupby(aggregtime)
            DSnew = DScomb.groupby(coordtime+'.'+grpby_method).apply(biasmean)
            DSnew = DSnew.to_dataset(name = varnsres)
            ... 
        elif "overperiod" not in aggregtime:
            resamplefreq=self.MetricCalcProg.ConvertAggregKey2Resample(aggregtime)
            DSnew = DScomb.resample(time=resamplefreq,keep_attrs=True).apply(biasmean)
            DSnew = DSnew.to_dataset(name = varnsres)
            ...
        #
        self.DSref.rename({namey : varnsref },inplace=True)
        self.DSproof.rename({namex : varnsproof },inplace=True)
        unitsnew=GeneralUtils.safe_access_bib('',KeyError,dicttest=self.DSref[varnsref].attrs,dictkey='units',errhandle=False)
        if unitsnew is None: unitsnew='-'
        longnew="temporal BIAS of "+str(GeneralUtils.safe_access_bib('', KeyError, dicttest=self.DSref[varnsref].attrs, \
            dictkey='long_name',errhandle=False))
        self.Update_Attributes(Datasetobj=DSnew,variable=varnsres,stdname=varnsres,units=unitsnew,longname=longnew)
        endresult = xarray.merge([endresult,DSnew])
    return endresult
正如您所见,我需要定义函数'bias'和'biasmean',以始终获得正确的结果,而不管聚合方法'aggregtime'。定义另一个度量,如“LinearCorrelation”,代码几乎相同:

def LinCorr_temporal(self,varns_result=None,aggregtime=None,dim_time=None):
    """ Compute the linear correlation for a timeseries -> e.g. R^3 --> R^2:
        LinCorr(x,y) = ???"""
    def correl2dtm(x):
        a = ( x[namex] - x[namex].mean(dim=coordtime) ) * ( x[namey] - x[namey].mean(dim=coordtime) ) \
            / x[namex].std(dim=coordtime) / x[namey].std(dim=coordtime)
        return a.mean(dim=coordtime)
    #
    endresult = xarray.Dataset()
    for varnsproof,varnsref,varnsres in zip(self.varns_proof,self.varns_ref,varns_result):
        # ensure that only time stamps are considerd being present in both datasets (otherwise LC>1)
        self.DSproof = self.DSproof[varnsproof].where(self.DSref[varnsref].notnull()).to_dataset(name=varnsproof) #harmonize the nan's between both datasets (independent calculations would destroy lincor), part A
        self.DSref   = self.DSref[varnsref].where(self.DSproof[varnsproof].notnull()).to_dataset(name=varnsref)   #harmonize the nan's between both datasets, part B
        # rename the data variables and combine both datasets for evaluation
        namex=varnsres+"_x"; namey=varnsres+"_y"
        self.DSref.rename({varnsref : namey },inplace=True)
        self.DSproof.rename({varnsproof : namex },inplace=True)
        DScomb = xarray.merge([self.DSref,self.DSproof])
        coordtime     = self.MetricCalcProg.ListDimsToXarray(dim_time[varnsref])     #extract the name of time coordinate
        #
        if aggregtime == 'fullperiod':
            DSnew = correl2dtm(DScomb).to_dataset(name = varnsres)
            ...
        elif aggregtime == '-':
            print(' The Linear Corr. computation makes no sense for each single time step ')
            exit()
        elif "overperiod" in aggregtime:
            grpby_method=self.MetricCalcProg.ConvertAggregKey2Groupby(aggregtime)
            DSnew = DScomb.groupby(coordtime+'.'+grpby_method).apply(correl2dtm)
            DSnew = DSnew.to_dataset(name = varnsres)
            ...
        elif "overperiod" not in aggregtime:
                            resamplefreq=self.MetricCalcProg.ConvertAggregKey2Resample(aggregtime)
            DSnew = DScomb.resample(time=resamplefreq,keep_attrs=True).apply(correl2dtm)
            DSnew = DSnew.to_dataset(name = varnsres)
            ...
        #
        self.DSref.rename({namey : varnsref },inplace=True)
        self.DSproof.rename({namex : varnsproof },inplace=True)
        unitsnew='1'
        longnew="temporal lin. correl. of "+str(GeneralUtils.safe_access_bib('', KeyError, dicttest=self.DSref[varnsref].attrs, \
            dictkey='long_name',errhandle=False))
        self.Update_Attributes(Datasetobj=DSnew,variable=varnsres,stdname=varnsres,units=unitsnew,longname=longnew)
        endresult = xarray.merge([endresult,DSnew])
    return endresult
如您所见,与“偏差”计算相比,只有微小的差异。函数定义不同。聚合时间“-”的异常仅出现在“LinCorr_temporal”和where语句中,该语句仅选择存在“notnull”数据的网格点


关于函数“def bias”和“def correl2dtm”的定义,您是否建议将此处定义的两种方法结合起来?我想有一种编程技术我至今还没有掌握,即动态定义函数。

函数是python中的对象,因此可以将它们分配给变量。您可以将它们作为函数参数传递:

def bias(x, namex, namey, coordtime=False):
    return (x[namex] - x[namey])

def correl2dtm(x, namex, namey, coordtime):
    a = (x[namex] - x[namex].mean(dim=coordtime)) * (x[namey] - x[namey].mean(dim=coordtime)) \
        / x[namex].std(dim=coordtime) / x[namey].std(dim=coordtime)
    return a.mean(dim=coordtime)

def temporal(self, func, varns_result=None,aggregtime=None,dim_time=None):
    ...
    DSnew = func(DScomb, namex, namey, coordtime).to_dataset(name = varnsres)
    ...

# call temporal() with bias function (= old BIAS_temporal)
temporal(bias, ...)

# call temporal() with correl2dtm (= old LinCorr_temporal)
temporal(correl2dtm, ...)

函数是python中的对象,因此可以将它们分配给变量。您可以将它们作为函数参数传递:

def bias(x, namex, namey, coordtime=False):
    return (x[namex] - x[namey])

def correl2dtm(x, namex, namey, coordtime):
    a = (x[namex] - x[namex].mean(dim=coordtime)) * (x[namey] - x[namey].mean(dim=coordtime)) \
        / x[namex].std(dim=coordtime) / x[namey].std(dim=coordtime)
    return a.mean(dim=coordtime)

def temporal(self, func, varns_result=None,aggregtime=None,dim_time=None):
    ...
    DSnew = func(DScomb, namex, namey, coordtime).to_dataset(name = varnsres)
    ...

# call temporal() with bias function (= old BIAS_temporal)
temporal(bias, ...)

# call temporal() with correl2dtm (= old LinCorr_temporal)
temporal(correl2dtm, ...)

偏差
等函数是在函数中定义的,而不是全局定义的,这有什么原因吗?没有,没有任何东西可以阻止全局定义它们。我只想让函数接近它们的执行调用。如果偏差定义更为全局,您是否看到了动态调用偏差定义等的机会?我会对ansatz背后的技术感兴趣。如果它们是全局定义的,您可以有条件地加载它们,例如
if is_bias:func=bias;否则:func=correl2dtm
。如果确实要动态定义它们,可以编写一个返回另一个函数的函数。'func=bias'将bias公式加载到名称'func'?我将用一个玩具的例子来试一下。但是,您在第二句中建议编写一个返回另一个函数的函数。我不知道这个概念,也许你有一个链接到一个这样做的例子。如果我不清楚,很抱歉。我在下面添加了一个更详细的答案。让我知道这是否是您想要的。是否有理由在函数中定义
偏差
等函数,而不是全局定义函数?不,没有任何东西可以阻止全局定义它们。我只想让函数接近它们的执行调用。如果偏差定义更为全局,您是否看到了动态调用偏差定义等的机会?我会对ansatz背后的技术感兴趣。如果它们是全局定义的,您可以有条件地加载它们,例如
if is_bias:func=bias;否则:func=correl2dtm
。如果确实要动态定义它们,可以编写一个返回另一个函数的函数。'func=bias'将bias公式加载到名称'func'?我将用一个玩具的例子来试一下。但是,您在第二句中建议编写一个返回另一个函数的函数。我不知道这个概念,也许你有一个链接到一个这样做的例子。如果我不清楚,很抱歉。我在下面添加了一个更详细的答案。让我知道这是否是您所寻找的全局定义的问题是def语句中的参数:“namex”、“namey”、“coordtime”。在这里的示例中,这些参数是在方法“temporal(…)”中定义的。def语句是否知道“namex”的最近值…?你是对的,我没有注意到这一点。我现在已经更新了代码段。一般来说,最好将参数显式传递给函数,而不是依赖全局变量。此解决方案很好,因为xarray支持应用功能的参数,即它们可以传递给要应用的函数:
dataarray.resample(time=“M”).apply(bias,namex,namey,coordtime)
我看到的全局定义的问题是def语句中的参数:“namex”、“namey”、“coordtime”。在这里的示例中,这些参数是在方法“temporal(…)”中定义的。def语句是否知道“namex”的最近值…?你是对的,我没有注意到这一点。我现在已经更新了代码段。一般来说,最好将参数显式地传递给函数,而不是依赖全局变量。此解决方案很好,因为xarray支持应用功能的参数,即它们可以传递给要应用的函数:
dataarray.resample(time=“M”).apply(bias,namex,namey,coordtime)