簡體   English   中英

如何使用Python讀取NetCDF文件並寫入CSV

[英]How to read NetCDF file and write to CSV using Python

我的目的是從netcdf文件訪問數據並以以下格式寫入CSV文件。

Latitude  Longitude Date1  Date2  Date3
100       200       <-- MIN_SFC values -->

到目前為止,我已經訪問了變量,將標頭寫入文件並填充了緯度/經度。

如何訪問指定的lon,lat坐標和日期的MIN_SFC值,然后將其寫入CSV文件。

我是python新手,如果有更好的方法可以解決這個問題,請告訴我。

NetCDF文件信息:

Dimensions:
  time = 7 
  latitude = 292
  longitude =341

Variables:
  float MIN_SFC (time=7, latitude = 292, longitude = 341)

這是我嘗試過的:

  from netCDF4 import Dataset, num2date filename = "C:/filename.nc" nc = Dataset(filename, 'r', Format='NETCDF4') print nc.variables print 'Variable List' for var in nc.variables: print var, var.units, var.shape # get coordinates variables lats = nc.variables['latitude'][:] lons = nc.variables['longitude'][:] sfc= nc.variables['Min_SFC'][:] times = nc.variables['time'][:] # convert date, how to store date only strip away time? print "Converting Dates" units = nc.variables['time'].units dates = num2date (times[:], units=units, calendar='365_day') #print [dates.strftime('%Y%m%d%H') for date in dates] header = ['Latitude', 'Longitude'] # append dates to header string for d in dates: print d header.append(d) # write to file import csv with open('Output.csv', 'wb') as csvFile: outputwriter = csv.writer(csvFile, delimiter=',') outputwriter.writerow(header) for lat, lon in zip(lats, lons): outputwriter.writerow( [lat, lon] ) # close the output file csvFile.close() # close netcdf nc.close() 

更新:

我已經更新了寫入CSV文件的代碼,這是一個屬性錯誤,因為經緯度是雙精度。

AttributeError:“ numpy.float32”對象沒有屬性“ append”

有什么辦法在python中強制轉換為字符串? 你認為這行得通嗎?

當我在控制台上打印值時,我注意到許多返回為“-”的值。 我想知道這是否代表定義為-32767.0的fillValue或missingValue。

我還想知道3d數據集的變量是否應該通過lats = nc.variables ['latitude'] [:] [:]或lats = nc.variables ['latitude'] [:] [:: ]?

 # the csv file is closed when you leave the block with open('output.csv', 'wb') as csvFile: outputwriter = csv.writer(csvFile, delimiter=',') for time_index, time in enumerate(times): # pull the dates out for the header t = num2date(time, units = units, calendar='365_day') header.append(t) outputwriter.writerow(header) for lat_index, lat in enumerate(lats): content = lat print lat_index for lon_index, lon in enumerate(lons): content.append(lon) print lon_index for time_index, time in enumerate(times): # for a date # pull out the data data = sfc[time_index,lat_index,lon_index] content.append(data) outputwriter.writerow(content) 

我會將數據加載到Pandas中,這有助於對時間序列數據進行分析和繪圖以及寫入CSV。

因此,這是一個真實的工作示例,該示例從指定的lon,lat位置中提取了一個波高的時間序列,並將其從全局預測模型數據集中導出。

注意:這里我們訪問OPeNDAP數據集,因此我們可以從遠程服務器提取所需的數據,而無需下載文件。 但是netCDF4對於刪除的OPeNDAP數據集或本地NetCDF文件的工作原理完全相同,這是非常有用的功能!

import netCDF4
import pandas as pd
import matplotlib.pyplot as plt

# NetCDF4-Python can read a remote OPeNDAP dataset or a local NetCDF file:
url='http://thredds.ucar.edu/thredds/dodsC/grib/NCEP/WW3/Global/Best'
nc = netCDF4.Dataset(url)
nc.variables.keys()

lat = nc.variables['lat'][:]
lon = nc.variables['lon'][:]
time_var = nc.variables['time']
dtime = netCDF4.num2date(time_var[:],time_var.units)

# determine what longitude convention is being used [-180,180], [0,360]
print lon.min(),lon.max()

# specify some location to extract time series
lati = 41.4; loni = -67.8 +360.0  # Georges Bank

# find closest index to specified value
def near(array,value):
    idx=(abs(array-value)).argmin()
    return idx

# Find nearest point to desired location (could also interpolate, but more work)
ix = near(lon, loni)
iy = near(lat, lati)

# Extract desired times.      
# 1. Select -+some days around the current time:
start = dt.datetime.utcnow()- dt.timedelta(days=3)
stop = dt.datetime.utcnow()+ dt.timedelta(days=3)
#       OR
# 2. Specify the exact time period you want:
#start = dt.datetime(2013,6,2,0,0,0)
#stop = dt.datetime(2013,6,3,0,0,0)

istart = netCDF4.date2index(start,time_var,select='nearest')
istop = netCDF4.date2index(stop,time_var,select='nearest')
print istart,istop

# Get all time records of variable [vname] at indices [iy,ix]
vname = 'Significant_height_of_wind_waves_surface'
#vname = 'surf_el'
var = nc.variables[vname]
hs = var[istart:istop,iy,ix]
tim = dtime[istart:istop]

# Create Pandas time series object
ts = pd.Series(hs,index=tim,name=vname)

# Use Pandas time series plot method
ts.plot(figsize(12,4),
   title='Location: Lon=%.2f, Lat=%.2f' % ( lon[ix], lat[iy]),legend=True)
plt.ylabel(var.units);

#write to a CSV file
ts.to_csv('time_series_from_netcdf.csv')

兩者都會創建此圖以驗證您是否擁有所需的數據: 在此處輸入圖片說明

並將所需的CSV文件time_series_from_netcdf.csv寫入磁盤。

您還可以在Wakari上查看,下載和/或運行此示例

Rich Signell的回答非常有幫助! 請注意,導入日期時間也很重要,提取時間時,必須使用以下代碼:

import datetime
import netCDF4
import pandas as pd
import matplotlib.pyplot as plt

...

# 2. Specify the exact time period you want:
start = datetime.datetime(2005,1,1,0,0,0)
stop = datetime.datetime(2010,12,31,0,0,0)

然后,我遍歷了數據集所需的所有區域。

不確定您仍然遇到什么問題,這看起來不錯。 我確實看到了:

# convert date, how to store date only strip away time?
 print "Converting Dates"
 units = nc.variables['time'].units
 dates = num2date (times[:], units=units, calendar='365_day')

您現在將日期作為python datetime對象

 #print [dates.strftime('%Y%m%d%H') for date in dates]

這就是您想要將它們作為字符串使用時所需要的-但是,如果只希望這一天,請刪除%H:

date_strings = [dates.strftime('%Y%m%d')表示日期中的日期]

如果您希望年,月日為數字,則datetime對象具有以下屬性:

dt.year,dt.month,dt.day

至於sfc變量-是一個3-d數組,因此要獲得特定值,您可以執行以下操作:

sfc [time_index,lat_index,lon_index]

作為3-D,有多種方法可以將其寫入csv文件,但我猜您可能想要類似的東西:

對於time_index,以enumerate(time)表示的時間:#提取該時間的數據data = sfc [time_index,:,:]#將日期寫入文件(也許)#...。現在遍歷“行”對於數據中的行:outputwriter.writerow([str(val)對於行中的val])

或類似的東西....

屬性錯誤的問題是因為content需要是一個列表,並且使用lat初始化它,而lat只是一個數字。 您需要將其填充到列表中。

關於3D變量, lats = nc.variables['latitude'][:]足以讀取所有數據。

更新:一起迭代lon / lat

這是用於列表和迭代的帶有mod的代碼:

# the csv file is closed when you leave the block
with open('output.csv', 'wb') as csvFile:
    outputwriter = csv.writer(csvFile, delimiter=',')
    for time_index, time in enumerate(times): # pull the dates out for the header
        t = num2date(time, units = units, calendar='365_day')
        header.append(t)
    outputwriter.writerow(header)

    for latlon_index, (lat,lon) in enumerate(zip(lats, lons)):
        content = [lat, lon] # Put lat and lon into list
        print latlon_index
        for time_index, time in enumerate(times): # for a date
            # pull out the data 
            data = sfc[time_index,lat_index,lon_index]
            content.append(data)
            outputwriter.writerow(content)``

我實際上並未嘗試運行此操作,因此可能存在其他隱患。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM