使用 xr.open_dataset 更改变量数据即数据点 '43768' 在读入 xarray 时返回 'b'0'

问题描述

我正在尝试读入一些模型数据以与观察数据进行比较。该数据具有对应于实际站名的 station_name。但是,当我使用 xr.open_dataset(file) 将其读入 python 时,它将 5 位电台名称分隔为与电台名称的一部分相对应的单个字符。我注意到 station_name 变量有 dtype='|S1' 这意味着它一次只读取一个字符。 IE。它会将 station_name 41004 分解为 b'4'、b'1'、b'0'、b'0'、b'4'。我想我需要一个函数来组合所有单独的字符串并从名称和撇号中删除 b 并删除零字符条目。是否有将 5 个字符组合回原始 station_name 并删除所有 b 和撇号的函数?正确执行此操作的 netCDF 函数与我正在寻找的等效函数stationID = netCDF4.chartostring(station[:]) 以下是 Python 中的数据变量读数:

Data variables:
station_name
(station,string40)
|S1
b'3' b'2' b'0' b'1' ... b'' b'' b''
array([[b'3',b'2',b'0',...,b'',b''],[b'3',b'4',[b'4',b'1',<br />
    [b'6',b'3',[b'6',b'']],dtype='|S1')

在 linux 中,当我使用 ncdump -v station_name filename.nc 时:

{  
dimensions:  
        time = UNLIMITED ; // (8 currently)  
        station = 240 ;  
        string40 = 40 ;  
variables:  
        double time(time) ;  
                time:long_name = "julian day (UT)" ;  
                time:standard_name = "time" ;  
                time:units = "days since 1990-01-01 00:00:00" ;  
                time:conventions = "Relative julian days with decimal part (as parts of the day)"  
 ;
                time:axis = "T" ;  
                time:calendar = "standard" ;  
        int station(station) ;  
                station:long_name = "station id" ;  
                station:_FillValue = -2147483647 ;  
                station:axis = "X" ;  
        int string40(string40) ;  
                string40:long_name = "station_name number of characters" ;  
                string40:_FillValue = -2147483647 ;  
                string40:axis = "W" ;  
        char station_name(station,string40) ;  
                station_name:long_name = "station name" ;  
                station_name:content = "XW" ;  
                station_name:associates = "station string40" ;  
        float longitude(time,station) ;  
                longitude:long_name = "longitude" ;  
                longitude:standard_name = "longitude" ;  
                longitude:globwave_name = "longitude" ;  
                longitude:units = "degree_east" ;  
                longitude:scale_factor = 1.f ;  
                longitude:add_offset = 0.f ;  
                longitude:valid_min = -180.f ;  
                longitude:valid_max = 360.f ;  
                longitude:_FillValue = 9.96921e+36f ;  
                longitude:content = "TX" ;  
                longitude:associates = "time station" ;  
        float latitude(time,station) ;  
                latitude:long_name = "latitude" ;  
                latitude:standard_name = "latitude" ;  
                latitude:globwave_name = "latitude" ;  
                latitude:units = "degree_north" ;  
                latitude:scale_factor = 1.f ;  
                latitude:add_offset = 0.f ;  
                latitude:valid_min = -90.f ;  
                latitude:valid_max = 180.f ;  
                latitude:_FillValue = 9.96921e+36f ;  
                latitude:content = "TX" ;  
                latitude:associates = "time station" ;  
        float hs(time,station) ;  
                hs:long_name = "spectral estimate of significant wave height" ;  
                hs:standard_name = "sea_surface_wave_significant_height" ;  
                hs:globwave_name = "significant_wave_height" ;  
                hs:units = "m" ;  
                hs:scale_factor = 1.f ;  
                hs:add_offset = 0.f ;  
                hs:valid_min = 0.f ;  
                hs:valid_max = 100.f ;  
                hs:_FillValue = 9.96921e+36f ;  
                hs:content = "TX" ;  
                hs:associates = "time station" ;  

// global attributes:  
                :product_name = "ww3.202104_tab.nc" ;  
                :area = "GLOBAL 1 deg grid lat 85" ;  
                :data_type = "OCO spectra 2D" ;  
                :format_version = "1.1" ;  
                :southernmost_latitude = "n/a" ;  
                :northernmost_latitude = "n/a" ;  
                :latitude_resolution = "n/a" ;  
                :westernmost_longitude = "n/a" ;  
                :easternmost_longitude = "n/a" ;  
                :longitude_resolution = "n/a" ;  
                :minimum_altitude = "n/a" ;  
                :maximum_altitude = "n/a" ;  
                :altitude_resolution = "n/a" ;  
                :start_date = "2021-04-01 03:00:00" ;  
                :stop_date = "2021-04-02 00:00:00" ;  
                :field_type = "3-hourly" ;  
data:

station_name =  
  "32012","34002","41049","41051","41052","41060",...  
  "64045","64046" ;  
} 

我不得不将其全部标记代码,但它是上面来自 xr_opendataset(file) 和 ncdump 的输出数据,只是为了避免混淆。

我试图修剪它,所以它不是那么长,但我认为查看完整的 ncdump 会有所帮助。

解决方法

似乎与解码有关。

也许试试这个:https://www.tutorialspoint.com/python/string_decode.htm

再看看 xr.open_dataset() 的所有解码选项:http://xarray.pydata.org/en/stable/generated/xarray.open_dataset.html

,

电台名称已保存为需要使用 chartostring 命令转换回可读字符串的字符。这可以正确读取站名(尽管使用 NetCDF4 而不是 xarray 在 netCDF 文件中读取:

import netCDF4 as nc

modelfile = filepath+file
model = nc.Dataset(modelfile)
strings = model.variables['station_name'][:]
stations = nc.chartostring(strings[:])

Output: array(['32012','34002','41001',...,'63115','63117','64045','64046'],dtype='<U40')

我目前不知道如何使用 xarray 执行此操作,因为修改为使用 xarry 读取变量的相同代码会产生错误:

AttributeError                            Traceback (most recent call last)
<ipython-input-11-87a0f3653b9d> in <module>
      1 # model.variables['station'][:]
      2 strings = model['station_name'][:][:]
----> 3 stations = nc.chartostring(strings[:])
      4 stations
AttributeError: 'DataArray' object has no attribute 'tobytes'

但是,我上面使用 NetCDF4 阅读的解决方案对我有用!