Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.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 2.7 “时变单位”;日期为%Y%m%d.%f“;在python iris中_Python 2.7_Python Iris - Fatal编程技术网

Python 2.7 “时变单位”;日期为%Y%m%d.%f“;在python iris中

Python 2.7 “时变单位”;日期为%Y%m%d.%f“;在python iris中,python-2.7,python-iris,Python 2.7,Python Iris,我希望有人能帮忙。我正在使用iris在python中运行一些气候模型(NetCDF文件)。在我添加了格式不同的最后一个模型之前,一切都很顺利。在新型号中,他们用于时间变量的单位是天,为%Y%m%d.%f,但在其他型号中,则是天,因为…。这意味着,当我试图约束时间变量时,会出现以下错误AttributeError:'numpy.float64'对象没有属性'year'。 我尝试使用iriscc添加年份变量。添加年(EARTH3,'time'),但这只会导致错误“单位有未定义的日历” 我想知道你是否

我希望有人能帮忙。我正在使用iris在python中运行一些气候模型(NetCDF文件)。在我添加了格式不同的最后一个模型之前,一切都很顺利。在新型号中,他们用于时间变量的单位是
天,为%Y%m%d.%f
,但在其他型号中,则是
天,因为…
。这意味着,当我试图约束时间变量时,会出现以下错误
AttributeError:'numpy.float64'对象没有属性'year'
。 我尝试使用iriscc添加年份变量。添加年(EARTH3,'time'),但这只会导致错误
“单位有未定义的日历”

我想知道你是否知道我该如何解决这个问题?我需要转换日历类型吗?还是有办法解决这个问题?我不知道该怎么做

谢谢大家!! 埃里卡

编辑:这是我的文件的完整代码模型CanESM2正在工作,但模型EARTH3没有-它是一个有趣的时间单位

import matplotlib.pyplot as plt
import iris
import iris.coord_categorisation as iriscc
import iris.plot as iplt
import iris.quickplot as qplt
import iris.analysis.cartography
import cf_units
from cf_units import Unit
import datetime
import numpy as np

def main():
    #-------------------------------------------------------------------------

    #bring in all the GCM models we need and give them a name
    CanESM2= '/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/GCM_data/tasmin_Amon_CanESM2_historical_r1i1p1_185001-200512.nc'
    EARTH3= '/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/GCM_data/tas_Amon_EC-EARTH_historical_r3i1p1_1850-2009.nc'

    #Load exactly one cube from given file
    CanESM2 = iris.load_cube(CanESM2)
    EARTH3 = iris.load_cube(EARTH3)

    print"CanESM2 time"
    print (CanESM2.coord('time'))
    print "EARTH3 time"
    print (EARTH3.coord('time'))

    #fix EARTH3 time units as they differ from all other models
    t_coord=EARTH3.coord('time')
    t_unit = t_coord.attributes['invalid_units']
    timestep, _, t_fmt_str = t_unit.split(' ')
    new_t_unit_str= '{} since 1850-01-01 00:00:00'.format(timestep) 
    new_t_unit = cf_units.Unit(new_t_unit_str, calendar=cf_units.CALENDAR_STANDARD)

    new_datetimes = [datetime.datetime.strptime(str(dt), t_fmt_str) for dt in t_coord.points]
    new_dt_points = [new_t_unit.date2num(new_dt) for new_dt in new_datetimes]
    new_t_coord = iris.coords.DimCoord(new_dt_points, standard_name='time', units=new_t_unit)

    print "EARTH3 new time"
    print (EARTH3.coord('time'))

    #regrid all models to have same latitude and longitude system, all regridded to model with lowest resolution
    CanESM2 = CanESM2.regrid(CanESM2, iris.analysis.Linear())
    EARTH3 =EARTH3.regrid(CanESM2, iris.analysis.Linear())

    #we are only interested in the latitude and longitude relevant to Malawi (has to be slightly larger than country boundary to take into account resolution of GCMs)
    Malawi = iris.Constraint(longitude=lambda v: 32.0 <= v <= 36., latitude=lambda v: -17. <= v <= -8.)   
    CanESM2 =CanESM2.extract(Malawi)
    EARTH3 =EARTH3.extract(Malawi)

    #time constraignt to make all series the same, for ERAINT this is 1990-2008 and for RCMs and GCMs this is 1961-2005
    iris.FUTURE.cell_datetime_objects = True
    t_constraint = iris.Constraint(time=lambda cell: 1961 <= cell.point.year <= 2005)
    CanESM2 =CanESM2.extract(t_constraint)
    EARTH3 =EARTH3.extract(t_constraint)

    #Convert units to match, CORDEX data is in Kelvin but Observed data in Celsius, we would like to show all data in Celsius
    CanESM2.convert_units('Celsius')
    EARTH3.units = Unit('Celsius') #this fixes EARTH3 which has no units defined
    EARTH3=EARTH3-273 #this converts the data manually from Kelvin to Celsius

    #add year data to files
    iriscc.add_year(CanESM2, 'time')
    iriscc.add_year(EARTH3, 'time')

    #We are interested in plotting the data by year, so we need to take a mean of all the data by year
    CanESM2YR=CanESM2.aggregated_by('year', iris.analysis.MEAN)
    EARTH3YR = EARTH3.aggregated_by('year', iris.analysis.MEAN)

    #Returns an array of area weights, with the same dimensions as the cube
    CanESM2YR_grid_areas = iris.analysis.cartography.area_weights(CanESM2YR)
    EARTH3YR_grid_areas = iris.analysis.cartography.area_weights(EARTH3YR)

    #We want to plot the mean for the whole region so we need a mean of all the lats and lons
    CanESM2YR_mean = CanESM2YR.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=CanESM2YR_grid_areas)   
    EARTH3YR_mean = EARTH3YR.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=EARTH3YR_grid_areas) 

    #-------------------------------------------------------------------------
    #PART 4: PLOT LINE GRAPH
    #limit x axis    
    plt.xlim((1961,2005)) 

    #assign the line colours and set x axis to 'year' rather than 'time'
    qplt.plot(CanESM2YR_mean.coord('year'), CanESM2YR_mean, label='CanESM2', lw=1.5, color='blue')
    qplt.plot(EARTH3YR_mean.coord('year'), EARTH3YR_mean, label='EC-EARTH (r3i1p1', lw=1.5, color='magenta')

    #set a title for the y axis
    plt.ylabel('Near-Surface Temperature (degrees Celsius)')

    #create a legend and set its location to under the graph
    plt.legend(loc="upper center", bbox_to_anchor=(0.5,-0.05), fancybox=True, shadow=True, ncol=2)

    #create a title
    plt.title('Tas for Malawi 1961-2005', fontsize=11)   

    #add grid lines
    plt.grid()

    #show the graph in the console
    iplt.show()

if __name__ == '__main__':
    main()
导入matplotlib.pyplot作为plt
进口虹膜
导入iris.coord_分类为iriscc
将iris.plot导入为iplt
将iris.quickplot导入为qplt
导入iris.analysis.Maptography
导入CFU单元
从cf_单元导入单元
导入日期时间
将numpy作为np导入
def main():
#-------------------------------------------------------------------------
#带上我们需要的所有GCM模型,并给它们命名
CanESM2='/exports/csce/datastore/geos/users/s0XXXX/Climate_modeling/GCM_data/tasmin_Amon_CanESM2_history_r1p1_185001-200512.nc'
EARTH3='/exports/csce/datastore/geos/users/s0XXXX/Climate_modeling/GCM_data/tas_Amon_EC-EARTH_history_r3i1p1_1850-2009.nc'
#从给定文件中只加载一个多维数据集
CanESM2=iris.load\u多维数据集(CanESM2)
EARTH3=iris.load\u立方体(EARTH3)
打印“CanESM2次”
打印(CanESM2.coord('time'))
打印“地球3次”
打印(EARTH3.coord(“时间”))
#固定EARTH3时间单位,因为它们不同于所有其他型号
t_coord=EARTH3.coord(‘时间’)
t_单位=t_坐标属性['invalid_单位']
timestep,u,t_fmt_str=t_unit.split(“”)
自1850-01-01 00:00:00以来的新单位{}。格式(时间步)
新单位=cf单位。单位(新单位,日历=cf单位。日历标准)
new_datetimes=[datetime.datetime.strtime(str(dt),t_fmt_str)表示t_坐标点中的dt]
new_dt_points=[new_t_unit.date2num(new_dt)表示new_dt在new_datetimes中]
新的坐标=iris.coords.DimCoord(新的坐标点,标准的时间,单位=新的单位)
打印“地球3新时间”
打印(EARTH3.coord(“时间”))
#将所有模型重新划分为具有相同的纬度和经度系统,所有模型重新划分为具有最低分辨率的模型
CanESM2=CanESM2.reglid(CanESM2,iris.analysis.Linear())
EARTH3=EARTH3.regrid(CanESM2,iris.analysis.Linear())
#我们只对与马拉维相关的纬度和经度感兴趣(考虑到GCMs的分辨率,必须略大于国家边界)

马拉维=iris.Constraint(经度=lambda v:32.0在iris中,时间坐标的单位字符串必须以
格式指定,因为
是时间的度量单位,例如“天”或“年”。iris库使用此格式提供有效单位并执行单位转换

在这种情况下,时间坐标没有遵循此格式的单位,这意味着时间坐标将没有完整的时间坐标功能(这部分解释了问题中的属性错误)。要解决此问题,我们需要基于现有时间坐标的值和元数据构建新的时间坐标,然后用新的时间坐标替换多维数据集的现有时间坐标

为此,我们需要:

  • 基于现有时间单位中包含的元数据构造新的时间单位
  • 使用现有时间单位中指定的格式字符串,获取现有时间坐标的点值并将其格式化为datetime对象
  • 使用(1)中构造的新时间单位将datetime对象从(2)转换为浮点数数组
  • 根据(3)中构造的数组和(1)中生成的新时间单位创建新的时间坐标
  • 从多维数据集中删除旧的时间坐标,然后添加新的时间坐标
  • 下面是执行此操作的代码

    import datetime
    import cf_units
    import iris
    import numpy as np
    
    t_coord = EARTH3.coord('time')
    
    t_unit = t_coord.attributes['invalid_units']
    timestep, _, t_fmt_str = t_unit.split(' ')
    new_t_unit_str = '{} since 1850-01-01 00:00:00'.format(timestep)
    new_t_unit = cf_units.Unit(new_t_unit_str, calendar=cf_units.CALENDAR_STANDARD)
    
    new_datetimes = [datetime.datetime.strptime(str(dt), t_fmt_str) for dt in t_coord.points]
    new_dt_points = [new_t_unit.date2num(new_dt) for new_dt in new_datetimes]
    new_t_coord = iris.coords.DimCoord(new_dt_points, standard_name='time', units=new_t_unit)
    
    t_coord_dim = cube.coord_dims('time')
    cube.remove_coord('time')
    cube.add_dim_coord(new_t_coord, t_coord_dim)
    
    我已经为您的时间数据做了一个关于最佳纪元的假设。我也对最能描述您的数据的日历做了一个假设,但是您应该能够(在构建
    新的\u\u单位
    时)将我选择的标准日历替换为任何其他有效的
    cf\u单位
    日历

    最后一点,实际上不可能更改日历类型。这是因为不同的日历类型包含和排除不同的日期。例如,360天的日历有2月30日,但没有5月31日(因为它假设12个理想化的30天长的月)。如果您尝试将360天日历转换为标准日历,您遇到的问题包括如何处理2月29日和30日的数据,以及如何填充360天日历中不存在的五天。由于这些原因,通常无法转换日历(Iris不允许此类操作)


    希望这能有所帮助!

    也许答案没有多大用处,但我在这里写了一个函数,该函数是我为了转换datetime数组中%Y%m%d.%f的数据而创建的

    函数创建一个完美的datetime数组,没有丢失的值,可以修改它以考虑是否有丢失的时间,但是气候模型不应该有丢失的数据

    def fromEARTHtime2Datetime(dt,timeVecEARTH):
        """
        This function returns the perfect array from the EARTH %Y%m%d.%f time 
        format and convert it to a more useful time, such as the time array
        from the datetime of pyhton, this is WHTOUT any missing data!
    
        Parameters
        ----------
        dt : string
            This is the time discretization, it can be 1h or 6h, but always it 
            needs to be hours, example dt = '6h'.
            
        timeVecEARTH : array of float
            Vector of the time to be converted. For example the time of the
            EARTH is day as %Y%m%d.%f.
            And only this format can be converted to datetime, for example:
                20490128.0,20490128.25,20490128.5,20490128.75 this will be converted
                in datetime: '2049-01-28 00:00:00', '2049-01-28 60:00:00',
                             '2049-01-28 12:00:00','2049-01-28 18:00:00'
    
        Returns
        -------
        timeArrNew : datetime
            This is the perfect and WITHOUT any missing data datatime array, 
            for example: DatetimeIndex(['2049-01-28 00:00:00', '2049-01-28 06:00:00',
                                            ...
                                       '2049-02-28 18:00:00', '2049-03-01 00:00:00'],
                                       dtype='datetime64[ns]', length=129, freq='6H')
    
        """
    
        dtDay = 24/np.float(dt[:-1])
        partOfDay = np.arange(0,1,1/dtDay)
        hDay = []
        for ip in partOfDay:
            hDay.append('%02.f:00:00' %(24*ip))
        dictHours = dict(zip(partOfDay,hDay))
        
        t0Str = str(timeVecEARTH[0])
        timeAux0 = t0Str.split('.')
        timeAux0 = timeAux0[0][0:4] +'-' + timeAux0[0][4:6] +'-' + timeAux0[0][6:] + ' ' + dictHours[float(timeAux0[1])]
        
        tendStr = str(timeVecEARTH[-1])
        timeAuxEnd = tendStr.split('.')
        timeAuxEnd = timeAuxEnd[0][0:4] +'-' + timeAuxEnd[0][4:6] +'-' + timeAuxEnd[0][6:] + ' ' + dictHours[float(timeAuxEnd[1])]
        
        timeArrNew = pd.date_range(timeAux0,timeAuxEnd, freq=dt)
        
        return timeArrNew
    
    

    您好@ErikaAWT–这是一个非常有趣的问题!我想我有一个解决方案,我将在近期发布,但为了帮助我使解决方案尽可能准确,您能用打印出的多维数据集的时间坐标更新您的问题吗?