numpy 如何根据文件名中的日期组合h5数据编号数组?

db2dz4w8  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(135)

我有成百上千个.h5文件,它们的文件名中包含日期(例如...20221017...)。对于每个文件,我都将一些参数提取到格式为Numy的数组中

[[param_1a, param_2a...param_5a],
  ... 
 [param_1x, param_2x,...param_5x]]

它表示感兴趣的数据。我想按月对数据进行分组,因此我有一个数组来表示30个数组的平均值,而不是(例如)一个月有30个数组。我怎么能这样做呢?
这就是我到目前为止所拥有的代码,FileName表示文件名的txt文件。

def combine_months(filename):
    fin = open(filename, 'r')
    next_name = fin.readline()
    while (next_name != ""):
        year = next_name[6:10]
        month = next_name[11:13]
        date = month+'\\'+year
        #not sure where to go from here
    fin.close()

我希望实现的一个例子是,例如,数组_1、数组_2、数组_3是数字数组,表示来自不同h5文件的数据,它们的文件名的日期是相同的月份。

array_1 = [[ 1  4 10]
           [ 2  5 11]
           [3  6 12]]
array_2 = [[ 1  2 5]
           [ 2  2 3]
           [ 3  6 12]]
array_3 = [[ 2  4 10]
           [ 3  2 3]
           [ 4  6 12]]

我希望结果看起来像这样:

2022_04_data = [[1,3,7.5]
                [2, 2, 6.5]
                [3,4,7.5]
                [4,6,12]]

请注意,每行的第一个数字代表一个ID,因此我还需要根据第一个数字将这些数据分组在一起。

dauxcl2d

dauxcl2d1#

好的,这是一个答案的开始。(我怀疑您在研究细节时可能会有更多问题。)
有几种方法可以获取文件名。您可以将它们放在一个文件中,但使用glob.iglob()函数更容易(也更好)。下面有两个示例,说明如何:1)打开每个文件,2)将数据从data数据集中读入数组,以及3)将数组追加到列表中。第一个示例将文件名显示在列表中。第二个使用glob.iglob()函数来获取文件名。(您还可以使用glob.glob()创建姓名列表。)

方法一:从列表中读取文件名

import h5py
arr_list = []
for h5file in ['20221001.h5', '20221002.h5', '20221003.h5']:    
    with h5py.File(h5file,'r') as h5f:    
        arr = h5f['data'][()]
        #print(arr)
        arr_list.append(arr)

方法二:使用lob.iglob()获取通配符文件

import h5py
from glob import iglob 
arr_list = []
for h5file in iglob('202210*.h5'):    
    with h5py.File(h5file,'r') as h5f:    
        print(h5f.keys()) # to get the dataset names from the keys
        arr = h5f['data'][()]
        #print(arr)
        arr_list.append(arr)

将数据集读入数组后,迭代列表、进行计算并根据结果创建新数组。下面的代码显示了如何获取shapedtype

for arr in arr_list:

# do something with the data based on column 0 value

    print(arr.shape, arr.dtype)

下面的代码显示了对具有匹配的第0列值的行进行求和的方法。在没有更多细节的情况下,很难确切地展示如何做到这一点。它将所有第0列的值读取到排序列表中,然后用来调整count和sum数组的大小,然后将其作为适当行的索引。


# first create a list from column 0 values, then sort

row_value_list = []
for arr in arr_list:
    col_vals = arr[:,0]
    for val in col_vals:
        if val not in row_value_list:
            row_value_list.append(val)

# Sort list of column IDs

row_value_list.sort()

# get length index list to create cnt and sum arrays

a0 = len(row_value_list) 

# get shape and dtype from 1st array, assume constant for all

a1 = arr_list[0].shape[1] 
dt = arr_list[0].dtype

arr_cnt = np.zeros(shape=(a0,a1),dtype=dt)
arr_cnt[:,0] = row_value_list
arr_sum = np.zeros(shape=(a0,a1),dtype=dt)
arr_sum[:,0] = row_value_list
for arr in arr_list:
    for row in arr:
        idx = row_value_list.index(row[0])
        arr_cnt[idx,1:] += 1
        arr_sum[idx,1:] += row[1:]

print('Count Array\n',arr_cnt)
print('Sum Array\n',arr_sum)

arr_ave = arr_sum/arr_cnt
arr_ave[:,0] = row_value_list
print('Average Array\n',arr_ave)

以下是从集合创建row_value_list的另一种方法。它更简单,因为集合不保留重复值,因此在将它们添加到row_value_set时不必检查现有值。


# first create a set from column 0 values, then create a sorted list

row_value_set = set()
for arr in arr_list:
    col_vals = set(arr[:,0])
    row_value_set = row_value_set.union(col_vals)
row_value_list = sorted(row_value_set)
6jygbczu

6jygbczu2#

这是一个新的、更新的答案,解决了关于计算中位数的评论/请求。(它还可以计算平均值,并且可以很容易地扩展以计算掩码数组中的其他统计信息。)
正如我在2022年11月4日的评论中所指出的,“从我的第一个答案开始,很快就变得复杂和难以理解”。这个过程与第一个答案相似,但又不同。它使用glob来获取文件名列表(而不是iglob)。它不是将H5数据集加载到数组列表中,而是将所有数据加载到单个数组中(数据在0轴上“堆叠”)。我不认为这会增加内存占用。但是,如果要加载大量非常大的数据集进行分析,则内存可能会成为一个问题。
程序摘要:
1.使用glob.glob()根据通配符将文件名加载到列表
1.根据文件数和1个数据集的大小分配一个数组来存放所有数据(arr_all)。
1.循环所有H5文件,将数据加载到arr_all
1.创建唯一组ID的排序列表(第0列值)
1.根据arr_all中唯一的行ID数和列数,分配数组以保存平均值/中位数(arr_meanarr_median)。
1.循环ID列表中的值,然后:
A.创建掩码数组(mask),其中第0列的值=循环值
B.广播mask以匹配arr_all形状,然后应用以创建ma_arr_all
C.循环遍历ma_arr_all列,压缩以获得未掩码的值,然后计算平均值和中位数并保存。
代码如下:

import h5py
from glob import glob 
import numpy as np

# use glob.glob() to get list of files using wildcard names

file_list = glob('202210*.h5')
with h5py.File(file_list[0],'r') as h5f:
    a0, a1 = h5f['data'].shape
    # allocate array to hold values from all datasets
    arr_all = np.zeros(shape=(len(file_list)*a0,a1), dtype=h5f['data'].dtype)

start, stop = 0, a0
for i, h5file in enumerate(file_list):    
    with h5py.File(h5file,'r') as h5f:       
        arr_all[start:stop,:] = h5f['data'][()]
        start += a0
        stop += a0

# Create a set from column 0 values, and use to create a sorted list

row_value_set = set(arr_all[:,0])
row_value_list = sorted(row_value_set)

arr_mean = np.zeros(shape=(len(row_value_list),arr_all.shape[1]))
arr_median = np.zeros(shape=(len(row_value_list),arr_all.shape[1]))

col_0 = arr_all[:,0:1]
for i, row_val in enumerate(row_value_list):
    row_mask = np.where(col_0==row_val, False, True ) # True mask value ignores data.
    all_mask= np.broadcast_to(row_mask, arr_all.shape)
    ma_arr_all = np.ma.masked_array(arr_all, mask=all_mask)    
    for j in range(ma_arr_all.shape[1]):
        masked_col = ma_arr_all[:,j:j+1].compressed()
        arr_mean[i:i+1,j:j+1] = np.mean(masked_col)
        arr_median[i:i+1,j:j+1] = np.median(masked_col)
print('Mean values:\n',arr_mean)    
print('Median values:\n',arr_median)

相关问题