gpt4 book ai didi

c# - 如何处理 NULLS : C#, Microsoft SDS 1.3 和 NetCDF 文件

转载 作者:太空狗 更新时间:2023-10-29 23:28:44 25 4
gpt4 key购买 nike

我正在编写一个使用 Microsoft Scientific Data-Set 读取 NetCDF 文件的 C# 程序。

using System;
using System.IO;
using sds = Microsoft.Research.Science.Data;
using Microsoft.Research.Science.Data.Imperative;


namespace NetCDFConsoleApp
{
class Program
{
static void Main(string[] args)
{
// Gets dataset from file.
var dataset = sds.DataSet.Open("E:\\Temp\\test.nc?openMode=readOnly");

// Get the starting DateTime from the meta data.
string dt = (string)dataset.Metadata["START_DATE"];

//load dataset into array
Single[,,] dataValues = dataset.GetData<float[,,]>("ACPR");

//Get DateTime from Metadata fields.
DateTime dt2 = DateTime.ParseExact(dt, "yyyy-MM-dd_HH:mm:ss", null);

// Latitude grid ranges from = 0 to 215; East Cape is ~ 125-144
for (int iLatitude = 137; iLatitude < 138; iLatitude++)
{
//Longitude ranges from 0 to 165; East Cape is ~ 125-150
for (int iLongitude = 133; iLongitude < 134; iLongitude++)
{
//There is normally 85 hours worth of data in a file. But not always...
for (int iTime = 0; iTime < 65; iTime++)
{
// Get each data point
float? thisValue = dataValues[iTime,iLatitude,iLongitude];

//Burp it out to the Console. Increment the datetime while im at it.
Console.WriteLine(dt.ToString() + ',' + dt2.ToString() + ',' + iTime.ToString() + ',' + dt2.AddHours(iTime) );
}
}
}

Console.ReadLine();

}
}
}

文件包含 map 网格 (X,Y) 上的预测降雨数据。每个网格引用应具有 85 小时的数据值(value)。

E:\temp>sds list test.nc
[2] ACPR of type Single (Time:85) (south_north:213) (west_east:165)
[1] Times of type SByte (Time:85) (DateStrLen:19)

但有时他们可能会更少(比如 60-70 小时)。当发生这种情况时,我的 C# 程序在导入数据时会失败。

var dataset = sds.DataSet.Open("test.nc?openMode=readOnly");
Single[,,] dataValues = dataset.GetData<Single[,,]>("ACPR");

我可以用命令行重现错误。

在这里,我可以成功提取 Grid XY 的 60-65 小时:125,130。我在此文件中的最后一个值是 Time=69。

E:\temp>sds data test.nc ACPR[60:65,125:125,130:130]
[2] ACPR of type Single (Time:85) (south_north:213) (west_east:165)
Name = ACPR
description = ACCUMULATED TOTAL GRID SCALE PRECIPITATION
MemoryOrder = XY
coordinates = XLONG XLAT XTIME
stagger =
FieldType = 104
units = mm

[60,125,130] 13.4926
[61,125,130] 15.24556
[62,125,130] 16.3638
[63,125,130] 17.39618
[64,125,130] 20.00507
[65,125,130] 23.57192

如果我尝试阅读过去的第 69 小时,我会收到以下错误。

E:\temp>sds data test.nc ACPR[60:70,125:125,130:130]
[2] ACPR of type Single (Time:85) (south_north:213) (west_east:165)
Name = ACPR
description = ACCUMULATED TOTAL GRID SCALE PRECIPITATION
MemoryOrder = XY
coordinates = XLONG XLAT XTIME
stagger =
FieldType = 104
units = mm

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at nc_get_vara_float(Int32 , Int32 , UInt64* , UInt64* , Single* )
at NetCDFInterop.NetCDF.nc_get_vara_float(Int32 ncid, Int32 varid, IntPtr[] start, IntPtr[] count, Single[] data)
at Microsoft.Research.Science.Data.NetCDF4.NetCdfVariable`1.ReadData(Int32[] origin, Int32[] shape)
at sdsutil.Program.PrintData(Variable v, String range, String format)
at sdsutil.Program.DoData(String uri, String[] args)
at sdsutil.Program.Main(String[] args)

E:\temp>

如果文件包含完整的 85 小时,我可以请求时间 0-100,它仍然给我 85 个值而没有错误。

我确信该问题是 NULL/缺失数据。在导入变量不为空的数据时,有什么方法可以指定吗?或使用某种尝试/捕获?

Single[,,] dataValues = dataset.GetData<Single[,,]>("ACPR")>> where it's not blank thanks. ;

编辑:我开始怀疑文件格式不正确。使用 SDS 查看器

Good file

Bad file

然而,命令行显示两者的元数据相同。

E:\temp>sds good.nc
[2] ACPR of type Single (Time:85) (south_north:213) (west_east:165)
[1] Times of type SByte (Time:85) (DateStrLen:19)

E:\temp>sds bad.nc
[2] ACPR of type Single (Time:85) (south_north:213) (west_east:165)
[1] Times of type SByte (Time:85) (DateStrLen:19)

E:\temp>

最佳答案

彼得,

由于错误在 ReadData(Int32[] origin, Int32[] shape) (你指出的一样);我看到两种可能的解决方案:

在深入研究解决方案之前,您需要决定是否可以将缺失数据视为 0.0 或是否需要将其视为缺失。如果 missing 不同于 0.0,则如果 null Not Acceptable ,则可能的 missing 可以编码为 -1.0。为缺失数据提出 -1.0 值是假设不可能出现负降雨值。

如果结果,dataValues , 可能包含空值,您需要做的就是将 float 替换为 float ?在行中:

float thisValue = dataValues[iTime,iLatitude,iLongitude];

成为:

float? thisValue = dataValues[iTime,iLatitude,iLongitude]; 

如果您在家免费使用 float?那么这是一个快乐的解决方案。 (您仍然需要决定如何处理空值。)

其他可能的解决方案 1)

调用Single[,,] dataValues = dataset.GetData<Single[,,]>("ACPR");后确保数组的最后一个索引大小 dataValues , 是 85。GetData(..) 可能不会填充所有 85 个字段,尤其是当第一行数据包含少于 85 个字段时。然后,如果需要,用 0 或 -1.0 手动替换空值。

然后当您检索数据时,您可以适本地处理空值、0 或 -1.0:

float? thisValue = dataValues[iTime,iLatitude,iLongitude];
// determine what to do with a null/0.0/-1.0 as a thisValue[..] value,
// .. potentially continue with the next iteration

可能的解决方案2)

如果您拥有 Single[,,] dataValues = dataset.GetData<Single[,,]>("ACPR"); 中的 GetData(..) 方法然后你确保它,GetData(..) , 提供所有 85 个值的工作,缺失值作为 nulls/0's/-1.0's 给出。然后,当您检索数据时,您可以适本地处理空值、0 或 -1.0。

干杯,

动画

关于c# - 如何处理 NULLS : C#, Microsoft SDS 1.3 和 NetCDF 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47861345/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com