2013-12-16 49 views
2

我有一些性能和'丑陋的代码'的问题,也许你可以帮助一些。 我必须导出数据从netCDF文件* .csv。为此,我编写了一些python代码。让我们拿一个3-dim netcdf文件:netCDF to * .csv without Loops(!)

def to3dim_csv(): 
    var = ncf.variables['H2O'] #e.g. data for 'H2O' values 
    one,two,three = var.shape #variable dimension shape e.g. (551,42,94) 
    dim1,dim2,dim3 = var.dimensions #dimensions e.g. (time,lat,lon) 

    if crit is not None: 
    bool1 = foo(dim1,crit,ncf) #boolean table: ("value important?",TRUE,FALSE) 
    bool2 = foo(dim2,crit,ncf) 
    bool3 = foo(dim3,crit,ncf) 

    writer.writerow([dim1,dim2,dim3,varn]) 
    for i in range(one): 
    for k in range(two): 
     for l in range(three): 
     if bool1[i] and bool2[k] and bool3[l]: 
      writer.writerow([ 
         ncf.variables[dim1][i], 
         ncf.variables[dim2][k], 
         ncf.variables[dim3][l], 
         var[i,k,l], 
         ]) 
    ofile.close() 

    # Sample csv output is like: 
    # time,lat,lon,H2O 
    # 1,90,10,100 
    # 1,90,11,90 
    # 1,91,10,101 

我想删除for val in range(d):块。也许使用recursiv功能,如:

var = ncf.variables['H2O'] 
dims = [d for d in var.dimensions] 
shapes = [var.variables[d].shape for d in dims] 
bools = [bool_table(d,crit,ncf) for d in dims] 
dims.append('H2O') 
writer.writerow(dims) 
magic_function(data) 

def magic_function(data): 

    [enter code] 

    writer.writerow(data) 
    magic_function(left_data) 

更新: 对于任何人谁是有兴趣的。此作品瞬间...

def data_to_table(dataset, var): 
    assert isinstance(dataset,xr.Dataset), 'Dataset must be xarray.Dataset' 
    obj = getattr(dataset, var) 
    table = np.zeros((obj.data.size, obj.data.ndim+1), dtype=np.object_) 
    table[:,0] = obj.data.flat 
    for i,d in enumerate(obj.dims): 
     repeat = np.prod(obj.data.shape[i+1:]) 
     tile = np.prod(obj.data.shape[:i]) 
     dim = getattr(dataset, d) 
     dimdata = dim.data 
     dimdata = np.repeat(dimdata, repeat) 
     dimdata = np.tile(dimdata, tile) 
     table[:,i+1] = dimdata.flat 
    return table 

def export_to_csv(dataset, var, filename, size=None): 
    obj = getattr(dataset, var) 
    header = [var] + [x for x in obj.dims] 
    tabular = data_to_table(dataset, var) 
    size = slice(None,size,None) if size else slice(None,None,None) 
    with open(filename, 'w') as f: 
     writer = csv.writer(f,dialect=csv.excel) 
     writer.writerow(header) 
     writer.writerows(tabular[size]) 
+0

1.如果我必须重复每个n-dim的代码,它看起来很丑。 2.需要花费大量的时间来浏览所有的数据。也许有人有一个使用'ncdump'或类似的功能来提高速度的想法 - [这个评论被删除我回答] – ucyo

+0

使用递归函数在这里不会带来性能增益 – goncalopp

+0

数组的numpy布尔索引应该加快速度? – M4rtini

回答

2

这样的事情。获取bol1 \ 2 \ 3的索引并在获取相关值时组合它们。

with open('numpy.csv', 'wb') as f: 
     out_csv = csv.writer(f) 
     header = ['dim1','dim2','dim3','varn'] 
     out_csv.writerow(header) 
     bol1_indices = np.nonzero(bol1)[0] 
     bol2_indices = np.nonzero(bol2)[0] 
     bol3_indices = np.nonzero(bol3)[0] 
     out_csv.writerows(([a[i, k, l], dim1[i], dim2[k], dim3[l]] for i in bol1_indices for k in bol2_indices for l in bol3_indices)) 
+0

谢谢M4rtini。这一个工程。它比环路快5-10%左右。你有没有其他提示? – ucyo

+0

实际上,在这种情况下,我认为大部分运行时间是从写入到文件部分。不知道如何加快速度。除了可能购买更快的硬盘。 – M4rtini

+0

Thx。希望你不要介意我不把它当作解决方案。我想等一会儿。也许一些netCDF专家可以暗示特殊的方法... – ucyo

0

在python中这样做总是会很慢,因为原始数据与您想要保存的格式不同。 Python将不得不创建索引并每行保存一个值。你需要什么csv?我推荐使用ncdump,它可以很快转换成简单的文本文件。如果您必须使用csv,则可以使用FAN language utilities中的nc2text实用程序(请参阅,例如this page)。

+0

我需要csv格式将数据保存到SciDB中。我会研究FAN并给你一些反馈。任何SciDB经验? – ucyo

+0

@UCU,不,我没有使用SciDB。 – tiago