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

How to make a histogram from this nc file?

我是一名研究助理,我最近开始学习 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()

现在我有一个格式为“(y)yy-mm-dd hh:mm:ss”的日期列表。我现在想获取这些日期并按月制作直方图(可能使用 matplotlib 或任何最适合此的方法)。因此,条形图 = 频率,箱子是月份。 另外,如果我的格式不清楚,有些年份有三个数字,有些只有两个,但实际上 none 有 1.

同样,我是 python 的新手,所以我很感激任何帮助,如果这个问题格式不正确,我深表歉意,因为我从未使用过这个网站。

谢谢!

我不知道你有什么数据,但这里有一个模拟示例,说明如何制作 x 轴上 months\days 的直方图。

我只能假设您从日期时间对象列表开始,但我无法弄清楚 nc 是什么(是 matplotlib.date 模块吗?)或者什么样的时间可以恰恰在独特的时代被发现。所以通常这就是方法。

您将需要和使用这些模块。

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

这些是我使用过的模拟日期。对于这个例子。那里只有 11 个月,所以大多数 bin 最终都会是 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)]

如果像上面的例子一样,你要处理不同的年份,你将不得不 "stack" 自己处理。否则,我稍后将使用的 date2num 函数将产生截然不同的数字。 To "stack" them 意味着将它们转换为就好像它们都发生在同一年一样。

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

此代码生成下图:

请注意,您有可能无法在原始图表上看到日期,因为它们会 运行 离开屏幕(此类格式可能很长,而且不适合图形)。在这种情况下,请按 "configure subplots" 按钮并调整 "bottom" 的值。在脚本中,您可以通过 plt.subplots_adjust(bottom=.3) 或其他一些值来实现。

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

还有一个更简单的方法,尽管更少 modifiable/personofiable 等...通过使用条形图而不是直方图的可能性。了解一下 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()