2015-02-19 2 views
0

Я научный сотрудник, и я недавно начал изучать python для интерпретации вывода модели в формате netCDF. Позвольте мне кратко рассказать о моем вопросе:Как сделать гистограмму из этого nc-файла?

Я уже просматривал определенную область сетки файла netCDF с использованием модуля netCDF4 и сохранял массив раз, который затем преобразовывал в список дат с использованием num2date netCDF4 особенность. Я показал свой код ниже. Обратите внимание, что limitedrange является подмножеством переменной из файла nc, а rmduplicates() не отображается.

import netCDF4 as nc 
import numpy as np 
import matplotlib.pyplot as pyp 
import matplotlib as mpl 
import datetime as dtm 
flor = nc.Dataset('FLOR.slp_subset1.nc','r')  

times = [] 
timecounter = .25 
for i in restrictedrange: 
    for j in np.nditer(i): 
     if(j <= 975): 
       times.append(timecounter) 
    timecounter += .25 
uniquetimes = rmduplicates(times) 
dates = nc.num2date(uniquetimes,'days since 0001-01-01 00:00:00','julian') 

stacked_dates = [] 
for date in dates: 
    stacked_dates.append(date.replace(year=0001)) 
stacked_dates = mpl.dates.date2num(stacked_dates) 

fig = pyp.figure() 
ax = pyp.subplot(111) 
ax.xaxis.set_major_locator(mpl.dates.MonthLocator()) 
format = mpl.dates.DateFormatter('%m/%d') 
ax.xaxis.set_major_formatter(format) 

ax.hist(stacked_dates) 

pyp.xticks(rotation='vertical') 

pyp.show() 

Теперь у меня есть список дат в формате «(у) уу-мм-дд чч: мм: сс». Теперь я хотел бы взять эти даты и сделать гистограмму (возможно, используя matplotlib или что-то лучшее для этого) по месяцам. Итак, бары = частота, ящики - месяцы. Кроме того, если это было не ясно из моего формата, некоторые годы имеют три числа, некоторые только два, но на самом деле их нет.

Опять же, я совершенно новый для питона, поэтому я ценю любую помощь, и я извините, если этот вопрос плохо отформатирован, поскольку я никогда не использовал этот сайт.

Спасибо!

+0

Неясно именно то, что вы хотите ... Я чувствую, как и большинство в начале этого вопроса на самом деле не имеет значения. Просто у вас есть список строковых дат и вы хотите получить гистограмму? – Ajean

+0

Я просто положил его там, чтобы было необходимо посмотреть, как я генерирую вывод (используя netCDF4 вместо matplotlib для num2date, например). Однако вы правы, у меня есть список строковых дат и вам нужна гистограмма, основанная на ежемесячной частоте. – LonelyHeartsClub

ответ

2

Я не знаю, что у вас есть для данных, но вот примерный пример того, как сделать гистограмму с месяцами \ дней на оси х.

Я могу только предположить, что вы начинаете со списка объектов datetime, но я не могу понять, что такое nc (это модуль matplotlib.date?) Или какие именно моменты могут быть найдены в уникальные времена , Так что вообще это подход.

Эти модули вам понадобятся и используются.

import matplotlib as mpl 
import matplotlib.pyplot as plt 
import datetime 

Это фальшивые даты, которые я использовал. для этого примера. Там всего 11 месяцев, поэтому в основном все бункеры будут в конце концов 1.

for i in range(1, 12): 
    dates.append(datetime.datetime(i*5+1960, i, i, i, i, i)) 

[datetime.datetime(1965, 1, 1, 1, 1, 1), datetime.datetime(1970, 2, 2, 2, 2, 2), datetime.datetime(1975, 3, 3, 3, 3, 3), datetime.datetime(1980, 4, 4, 4, 4, 4), datetime.datetime(1985, 5, 5, 5, 5, 5), datetime.datetime(1990, 6, 6, 6, 6, 6), datetime.datetime(1995, 7, 7, 7, 7, 7), datetime.datetime(2000, 8, 8, 8, 8, 8), datetime.datetime(2005, 9, 9, 9, 9, 9), datetime.datetime(2010, 10, 10, 10, 10, 10), datetime.datetime(2015, 11, 11, 11, 11, 11)] 

Если, как в приведенном выше примере вы имеете дело с различными лет, вы будете иметь в «стек» их самостоятельно. В противном случае функция date2num, которую я буду использовать позже, произведет совершенно разные цифры. Для их «стека» они преобразуют их, как если бы они все происходили в том же году.

stacked_dates = [] 
for date in dates: 
    stacked_dates.append(date.replace(year=2000) ) 

>>> stacked_dates 
[datetime.datetime(2000, 1, 1, 1, 1, 1), datetime.datetime(2000, 2, 2, 2, 2, 2), datetime.datetime(2000, 3, 3, 3, 3, 3), datetime.datetime(2000, 4, 4, 4, 4, 4), datetime.datetime(2000, 5, 5, 5, 5, 5), datetime.datetime(2000, 6, 6, 6, 6, 6), datetime.datetime(2000, 7, 7, 7, 7, 7), datetime.datetime(2000, 8, 8, 8, 8, 8), datetime.datetime(2000, 9, 9, 9, 9, 9), datetime.datetime(2000, 10, 10, 10, 10, 10), datetime.datetime(2000, 11, 11, 11, 11, 11)] 

Ok. Теперь мы можем использовать функцию date2num, чтобы получить что-то mpl на самом деле понимает. (Кстати, если вы хотите построить только эти данные вы можете с plt.plot_dates функции, эта функция понимает даты-времени объекты)

stacked_dates = mpl.dates.date2num(stacked_dates) 

>>> stacked_dates 
array([ 730120.04237269, 730152.08474537, 730182.12711806, 
     730214.16949074, 730245.21186343, 730277.25423611, 
     730308.2966088 , 730340.33898148, 730372.38135417, 
     730403.42372685, 730435.46609954]) 

Ok теперь для себя черчения. mpl может понять эти цифры, но он будет не автоматически считать, что это даты. Он будет относиться к ним как к нормальным цифрам. Вот почему мы должны сказать оси x, что они на самом деле являются датами.Делайте это с major_axis_formatter и set_major_locator

fig = plt.figure() 
ax = plt.subplot(111) 
ax.xaxis.set_major_locator(mpl.dates.MonthLocator()) 
format = mpl.dates.DateFormatter('%m/%d') #explore other options of display 
ax.xaxis.set_major_formatter(format) 

ax.hist(stacked_dates) #plot the damned thing 

plt.xticks(rotation='vertical') #avoid overlapping numbers 
          #make sure you do this AFTER .hist function 

plt.show() 

Этот код производит следующий график:

enter image description here

Обратите внимание, что есть шанс, что вы не сможете увидеть дату на оригинальном графике, потому что они ll run off screen (форматы, подобные этим, могут быть длинными и не помещаться на графике). В этом случае нажмите кнопку «настроить подзаголовки» и настройте значение «bottom». В скрипте вы можете сделать это с помощью plt.subplots_adjust(bottom=.3) или другого значения.

Вы также должны позаботиться, чтобы указать, что в ax.hist(stacked_dates, bins=12) есть 12 ящиков, потому что по умолчанию 10, и будет выглядеть фанки, как мой график.

Также существует более простая, хотя и менее модифицируемая/персонифицированная и т. Д. Возможность, используя график штрихов, а не гистограмму. Читайте об этом HERE Но это действительно зависит от того, какая у вас информация. Если много дат, возможно, проще позволить функции hist вычислить высоты бинов, чем сделать это самостоятельно. Если это какая-то другая информация, стоит рассмотреть возможность использования барного графика.

Полный сценарий будет что-то вроде:

import matplotlib as mpl 
import matplotlib.pyplot as plt 
import datetime 

stacked_dates = [] 
for date in dates: 
    stacked_dates.append(date.replace(year=2000) ) 

stacked_dates = mpl.dates.date2num(stacked_dates) 

fig = plt.figure() 
ax = plt.subplot(111) 
ax.xaxis.set_major_locator(mpl.dates.MonthLocator()) 
format = mpl.dates.DateFormatter('%m/%d') 
ax.xaxis.set_major_formatter(format) 

ax.hist(stacked_dates) 

plt.xticks(rotation='vertical') 
plt.show() 
+0

Благодарим за помощь. Я должен был указать, что такое nc (опять же, я новичок, поэтому мои извинения). Я импортировал модуль netCDF4 как nc в свой код и сделал это с помощью функции num2date netCDF4. Моя причина для использования этого заключается в том, что календар, используемый этим файлом, является юлианским, а не григорианским (как использует mpl). Есть ли способ использовать mpl без перекоса дат в течение дня или около того из-за разницы календаря? – LonelyHeartsClub

+0

Просто быстрое наблюдение, я думаю, что разница в каланде мешает мне перешагнуть шаг стекирования, так как даже при преобразовании моего времени в даты с использованием mpl я продолжаю получать ошибку «ValueError: день выходит за пределы диапазона в течение месяца». – LonelyHeartsClub

+0

@LonelyHeartsClub Ах, я не знал, что nc имеет ту же функцию. Что касается вашего первого вопроса, да. Отправьте некоторый код и дайте мне посмотреть, как вы его конвертируете. Насколько я понял, модуль netcdftime - это всего лишь бит-пакетный модуль datetime. Я бы рекомендовал сделать преобразование явно, например, 'для даты в ncdate: list.append (datetime (year = date.year .... day = date.day-1)' Это дает вам возможность иметь 'if' условия и т. д., чтобы точно контролировать, как происходит преобразование. Единственная проблема, которую я вижу, - это даты до 1500. Однако, если вы не используете старую информацию, не проблема. – ljetibo