如何从这个nc文件制作直方图?

时间:2015-02-19 23:13:14

标签: python date matplotlib histogram

我是研究助理,我最近开始学习python来解释netCDF文件格式的模型输出。让我快速回答一下我的问题:

我已经使用netCDF4模块搜索了netCDF文件的某个网格区域并存储了一些数组,然后我使用netCDF4的num2date功能将其转换为日期列表。我在下面显示了我的代码。请注意,restrictedrange是来自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()

现在我有一个日期列表,格式为&#34;(y)yy-mm-dd hh:mm:ss&#34;。我现在想采取这些日期并按月制作直方图(可能使用matplotlib或其他最好的方法)。所以,条形=频率,条形是几个月。 另外,如果我的格式不清楚,有些年份有三个数字,有些只有两个,但实际上没有一个有数字。

同样,我对python很新,所以我感谢任何帮助,如果这个问题格式不正确,我会道歉,因为我从未使用过这个网站。

谢谢!

1 个答案:

答案 0 :(得分:2)

我不知道你有什么数据,但这是一个模拟的例子,说明如何在x轴上制作月数\天的直方图。

我只能假设您从一个日期时间对象列表开始,但我无法弄清楚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)]

确定。现在我们可以使用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])

现在好了,为了绘图本身。 mpl可以理解这些数字,但会自动假设它们是日期。它会将它们视为正常数字。这就是为什么我们必须告诉x轴它们实际上是日期。使用major_axis_formatterset_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

请注意,您可能无法在原始图表上看到日期,因为它们会在屏幕外运行(这些格式可能很长,而且不适合图表)。在这种情况下,按“配置子图”按钮并调整“底部”的值。在脚本中,您可以通过plt.subplots_adjust(bottom=.3)或其他值来执行此操作。

您还应注意指定ax.hist(stacked_dates, bins=12)中有12个分箱,因为默认值为10,并且看起来像我的图表一样时髦。

此外,通过使用条形图而不是直方图,可以实现更简单,尽管更少可修改/可人性等等。阅读它HERE但它实际上取决于你有什么样的信息。如果它是很多日期,那么让hist函数计算bin高度比自己做更容易。 如果是其他信息,那么值得考虑使用条形图。

完整的脚本将类似于:

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()