Python Iris Установить ограничение по оси X и галочки

Я создаю линейные графики с указанием года или месяца по оси x.

Вот упрощенный код для ежемесячного линейного графика:

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

#this file is split into parts as follows:
    #PART 1: load and format CORDEX models
    #PART 2: load and format observed data
    #PART 3: format data
    #PART 4: plot data

def main():
    #PART 1: CORDEX MODELS
    #bring in all the models we need and give them a name
    CCCma = '/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/AFR_44_tas/ERAINT/1979-2012/tas_AFR-44_ECMWF-ERAINT_evaluation_r1i1p1_CCCma-CanRCM4_r2_mon_198901-200912.nc'

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


    #remove flat latitude and longitude and only use grid latitude and grid longitude to make consistent with the observed data, also make sure all of the longitudes are monotonic 
    lats = iris.coords.DimCoord(CCCma.coord('latitude').points[:,0], \
                                standard_name='latitude', units='degrees')
    lons = CCCma.coord('longitude').points[0]
    for i in range(len(lons)):
        if lons[i]>100.:
            lons[i] = lons[i]-360.
    lons = iris.coords.DimCoord(lons, \
                                standard_name='longitude', units='degrees')

    CCCma.remove_coord('latitude')
    CCCma.remove_coord('longitude')
    CCCma.remove_coord('grid_latitude')
    CCCma.remove_coord('grid_longitude')
    CCCma.add_dim_coord(lats, 1)
    CCCma.add_dim_coord(lons, 2)

    #we are only interested in the latitude and longitude relevant to Malawi

    Malawi = iris.Constraint(longitude=lambda v: 32.5 <= v <= 36., \
                         latitude=lambda v: -17. <= v <= -9.) 

    CCCma = CCCma.extract(Malawi)

    #time constraignt to make all series the same
    iris.FUTURE.cell_datetime_objects = True
    t_constraint = iris.Constraint(time=lambda cell: 1989 <= cell.point.year <= 2008)
    CCCma = CCCma.extract(t_constraint)



    #PART 2: OBSERVED DATA
    #bring in all the files we need and give them a name
    CRU= '/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Actual_Data/cru_ts4.00.1901.2015.tmp.dat.nc'

    #Load exactly one cube from given file
    CRU = iris.load_cube(CRU, 'near-surface temperature')

    #define the latitude and longitude
    lats = iris.coords.DimCoord(CRU.coord('latitude').points, \
                                standard_name='latitude', units='degrees')
    lons = CRU.coord('longitude').points

    #we are only interested in the latitude and longitude relevant to Malawi 
    Malawi = iris.Constraint(longitude=lambda v: 32.5 <= v <= 36., \
                         latitude=lambda v: -17. <= v <= -9.) 
    CRU = CRU.extract(Malawi)

    #time constraignt to make all series the same
    iris.FUTURE.cell_datetime_objects = True
    t_constraint = iris.Constraint(time=lambda cell: 1989 <= cell.point.year <= 2008)
    CRU = CRU.extract(t_constraint)



    #PART 3: FORMAT DATA  
    #data is in Kelvin, but we would like to show it in Celcius
    CCCma.convert_units('Celsius')                                                    

    #bring time data into allignment
    new_unit = cf_units.Unit('days since 1900-01-01', calendar = '365_day')
    CCCma.coord('time').convert_units(new_unit)                                                  

    #add years and months to data
    iriscc.add_year(CCCma, 'time')
    iriscc.add_year(CRU, 'time')
    iriscc.add_month(CCCma, 'time')
    iriscc.add_month(CRU, 'time')

    #We are interested in plotting the data by month, so we need to take a mean of all the data by month
    CCCmaYR = CCCma.aggregated_by('month', iris.analysis.MEAN)
    CRUYR = CRU.aggregated_by('month', iris.analysis.MEAN) 

    #regridding scheme requires spatial areas, therefore the longitude and latitude coordinates must be bounded. If the longitude and latitude bounds are not defined in the cube we can guess the bounds based on the coordinates
    CCCmaYR.coord('latitude').guess_bounds()
    CCCmaYR.coord('longitude').guess_bounds()
    CRUYR.coord('latitude').guess_bounds()
    CRUYR.coord('longitude').guess_bounds()

    #Returns an array of area weights, with the same dimensions as the cube
    CCCmaYR_grid_areas = iris.analysis.cartography.area_weights(CCCmaYR)
    CRUYR_grid_areas = iris.analysis.cartography.area_weights(CRUYR)

    #We want to plot the mean for the whole region so we need a mean of all the lats and lons
    CCCmaYR_mean = CCCmaYR.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=CCCmaYR_grid_areas) 
    CRUYR_mean = CRUYR.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=CRUYR_grid_areas)


    #PART 4: PLOT LINE GRAPH                                                                                               
    #assign the line colours and set x axis to months
    qplt.plot(CCCmaYR_mean.coord('month'),CCCmaYR_mean, label='CanRCM4_ERAINT', lw=1.5, color='blue')
    qplt.plot(CRUYR_mean.coord('month'), CRUYR_mean, label='Observed', lw=2, color='black')

    #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('Mean Near Surface Temperature for Malawi by month 1989-2008', fontsize=11)   

    #add grid lines
    plt.grid()

    #save the image of the graph and include full legend
    #plt.savefig('ERAINT_Temperature_LineGraph_Annual', bbox_inches='tight')

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

if __name__ == '__main__':
    main()

Это создает график, который выглядит следующим образом: введите здесь описание изображения

Как изменить галочки, чтобы отображались названия всех месяцев? Я также хотел бы, чтобы график заканчивался в декабре (без пробелов после).

Точно так же для годового линейного графика приведен упрощенный код:

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

#this file is split into parts as follows:
    #PART 1: load and format CORDEX models
    #PART 2: load and format observed data
    #PART 3: format data
    #PART 4: plot data

def main():
    #PART 1: CORDEX MODELS
    #bring in all the models we need and give them a name
    CCCma = '/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/AFR_44_tas/ERAINT/1979-2012/tas_AFR-44_ECMWF-ERAINT_evaluation_r1i1p1_CCCma-CanRCM4_r2_mon_198901-200912.nc'  

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

    #remove flat latitude and longitude and only use grid latitude and grid longitude to make consistent with the observed data, also make sure all of the longitudes are monotonic 
    lats = iris.coords.DimCoord(CCCma.coord('latitude').points[:,0], \
                                standard_name='latitude', units='degrees')
    lons = CCCma.coord('longitude').points[0]
    for i in range(len(lons)):
        if lons[i]>100.:
            lons[i] = lons[i]-360.
    lons = iris.coords.DimCoord(lons, \
                                standard_name='longitude', units='degrees')

    CCCma.remove_coord('latitude')
    CCCma.remove_coord('longitude')
    CCCma.remove_coord('grid_latitude')
    CCCma.remove_coord('grid_longitude')
    CCCma.add_dim_coord(lats, 1)
    CCCma.add_dim_coord(lons, 2)

    #we are only interested in the latitude and longitude relevant to Malawi      
    Malawi = iris.Constraint(longitude=lambda v: 32.5 <= v <= 36., \
                         latitude=lambda v: -17. <= v <= -9.) 

    CCCma = CCCma.extract(Malawi)

    #time constraignt to make all series the same
    iris.FUTURE.cell_datetime_objects = True
    t_constraint = iris.Constraint(time=lambda cell: 1989 <= cell.point.year <= 2008)

    CCCma = CCCma.extract(t_constraint)                                               


    #PART 2: OBSERVED DATA

    #bring in all the files we need and give them a name
    CRU= '/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Actual_Data/cru_ts4.00.1901.2015.tmp.dat.nc'

    #Load exactly one cube from given file
    CRU = iris.load_cube(CRU, 'near-surface temperature')

    #define the latitude and longitude
    lats = iris.coords.DimCoord(CRU.coord('latitude').points, \
                                standard_name='latitude', units='degrees')
    lons = CRU.coord('longitude').points

    #we are only interested in the latitude and longitude relevant to Malawi 
    Malawi = iris.Constraint(longitude=lambda v: 32.5 <= v <= 36., \
                         latitude=lambda v: -17. <= v <= -9.) 
    CRU = CRU.extract(Malawi)

    #time constraignt to make all series the same
    iris.FUTURE.cell_datetime_objects = True
    t_constraint = iris.Constraint(time=lambda cell: 1989 <= cell.point.year <= 2008)
    CRU = CRU.extract(t_constraint)

    #PART 3: FORMAT DATA       
    #data is in Kelvin, but we would like to show it in Celcius
    CCCma.convert_units('Celsius') 

    #add years to data
    iriscc.add_year(CCCma, 'time')
    iriscc.add_year(CRU, 'time')

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

    #regridding scheme requires spatial areas, therefore the longitude and latitude coordinates must be bounded. If the longitude and latitude bounds are not defined in the cube we can guess the bounds based on the coordinates
    CCCma.coord('latitude').guess_bounds()
    CCCma.coord('longitude').guess_bounds()
    CRU.coord('latitude').guess_bounds()
    CRU.coord('longitude').guess_bounds()

    #Returns an array of area weights, with the same dimensions as the cube
    CCCma_grid_areas = iris.analysis.cartography.area_weights(CCCma)
    CRU_grid_areas = iris.analysis.cartography.area_weights(CRU)

    #We want to plot the mean for the whole region so we need a mean of all the lats and lons
    CCCma_mean = CCCma.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=CCCma_grid_areas)
    CRU_mean = CRU.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=CRU_grid_areas)                                              



    #PART 4: PLOT LINE GRAPH  
    #assign the line colours
    qplt.plot(CCCma_mean.coord('year'), CCCma_mean, label='CanRCM4_ERAINT', lw=1.5, color='blue')
    qplt.plot(CRU_mean.coord('year'), CRU_mean, label='Observed', lw=2, color='black')

    #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('Mean Near Surface Temperature for Malawi 1989-2008', fontsize=11)   

    #add grid lines
    plt.grid()

    #save the image of the graph and include full legend
    #plt.savefig('ERAINT_Temperature_LineGraph_Annual', bbox_inches='tight')

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




if __name__ == '__main__':
    main()

и это создает этот график: введите здесь описание изображения

Как вы можете видеть, я ограничил свои данные с 1989 по 2008 год, но ось идет с 1985 по 2010 год, как я могу сделать это более точным?

Благодарю вас!


person ErikaAWT    schedule 18.09.2017    source источник
comment
Ваш упрощенный код на самом деле совсем не очень прост - можете ли вы воссоздать свою проблему, используя минимальный пример с данными, которые мы действительно можем воссоздать?   -  person Ken Syme    schedule 18.09.2017
comment
извините, я запускаю его с несколькими моделями и наблюдаемыми наборами данных. Поэтому, когда я сказал «упрощенный», я имел в виду только то, что оставил только по одному из каждого. Нет ли простого способа ограничить то, что отображает ось X?   -  person ErikaAWT    schedule 18.09.2017
comment
Можете ли вы хотя бы собрать всю загрузку и обработку данных и просто дать простой массив/фрейм данных с датами и значениями, которые вы пытаетесь построить? В настоящее время никто не сможет помочь, поскольку мы не можем получить данные, которые вы используете, и, честно говоря, это не важно для вашей проблемы!   -  person Ken Syme    schedule 18.09.2017
comment
Обычный способ установки ограничений — использовать plt.xlim( (xmin, xmax) ). Однако я не уверен, какой именно формат данных вы используете, и matplotlib может творить чудеса при использовании дат на оси x, что, вероятно, вам нужно, особенно для версии месяцев.   -  person Ken Syme    schedule 18.09.2017
comment
Спасибо, что помогли исправить годовые графики! Очень полезно. Есть ли аналогичный код, когда ось x не числовая (например, названия месяцев)? Кроме того, как вы устанавливаете галочки, если они не числовые?   -  person ErikaAWT    schedule 18.09.2017
comment
Вот где это зависит от того, как данные были нанесены на график - обычно они должны быть числовыми, поэтому, возможно, установите тики на что-то вроде plt.xticks(range(12), calendar.month_abbr[1:13]).   -  person Ken Syme    schedule 18.09.2017
comment
Спасибо за это. Поэтому мне пришлось сначала добавить номер_месяца к данным с помощью этого кода: iriscc.add_month_number(CCCma,'time') iriscc.add_month_number(CRU,'time'), а затем добавить в ваш код plt.xticks(range(12), calendar.month_abbr[0:12]) Теперь внизу отображаются все месяцы (кроме декабря, как ни странно), но все данные есть, только не метка декабря. . Спасибо!   -  person ErikaAWT    schedule 18.09.2017
comment
о, мне также пришлось import calendar и изменить ось x в qplot qplt.plot(CCCmaYR_mean.coord('month_number'),CCCmaYR_mean, label='CanRCM4_ERAINT', lw=1.5, color='blue') qplt.plot(CRUYR_mean.coord('month_number'), CRUYR_mean, label='Observed', lw=2, color='black')   -  person ErikaAWT    schedule 18.09.2017


Ответы (1)


Для вашего ежемесячного графика вы можете изменить его, установив xticks - это должно быть числовое, но вы также можете установить метки для использования вместо чисел. Что-то типа

plt.xticks(range(12), calendar.month_abbr[1:13])

может работать (зависит от формата ваших данных, вам может потребоваться указать номер месяца, а не название месяца). Вам нужно будет import calendar, чтобы заставить вышеперечисленное работать.

Для вашего годового графика вы должны просто установить пределы оси X, используя

plt.xlim((xmin, xmax))

где xmin — это, вероятно, 1989 год, а xmax — это 2008 год.

person Ken Syme    schedule 18.09.2017