簡體   English   中英

如何根據文件名中的日期合並h5數據numpy arrays?

[英]How to combine h5 data numpy arrays based on date in filename?

我有數百個 .h5 文件,文件名中有日期(例如 ..20221017...)。 對於每個文件,我都將一些參數提取到格式為 numpy 的數組中

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

代表感興趣的數據。 我想按月對數據進行分組,所以我沒有(例如)30 個 arrays 一個月,而是有 1 個數組代表 30 個 arrays 的平均值。我該怎么做?

這是我到目前為止的代碼,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()

我希望實現的一個例子是,array_1、array_2、array_3 是 numpy arrays,代表來自文件名日期相同月份的不同 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,因此我也需要根據第一個數字將這些數據分組在一起。

好的,這是答案的開始。 (我懷疑您在研究細節時可能會有更多問題。)

有幾種方法可以獲取文件名。 您可以將它們放在一個文件中,但是使用glob.iglob() function 更容易(並且更好的恕我直言)。下面有 2 個示例說明如何:1) 打開每個文件,2) 從數據中讀取data數據集到一個數組,和 3) append 數組到一個列表。 第一個示例在列表中包含文件名。 第二個使用glob.iglob() function 來獲取文件名。 (您也可以使用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)

方法二:使用glob.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)

在將數據集讀入 arrays 后,您遍歷列表,進行計算並根據結果創建一個新數組。 下面的代碼顯示了如何獲取shapedtype

for arr in arr_list:
# do something with the data based on column 0 value
    print(arr.shape, arr.dtype)

下面的代碼顯示了一種對具有匹配列 0 值的行求和的方法。 沒有更多細節,很難准確地展示如何做到這一點。 它將所有列 0 值讀入排序列表,然后使用大小計數和總和 arrays,然后作為正確行的索引。

# 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)

這是一個新的、更新的答案,解決了關於計算中位數的評論/請求。 (它還計算均值,並且可以輕松擴展以計算掩碼數組的其他統計數據。)

正如我在 2022 年 11 月 4 日的評論中指出的那樣,“從我的第一個答案開始,很快就變得復雜且難以理解”。 這個過程與第一個答案相似但不同。 它使用glob來獲取文件名列表(而不是iglob )。 它不是將 H5 數據集加載到 arrays 的列表中,而是將所有數據加載到一個數組中(數據“堆疊”在 0 軸上。)。 我認為這不會增加 memory 的占用空間。 但是,如果加載大量非常大的數據集進行分析,memory 可能會成為問題。

程序概要:

  1. 使用glob.glob()將文件名加載到基於通配符的列表中
  2. 根據文件的數量和 1 個數據集的大小分配一個數組來保存所有數據 ( arr_all )。
  3. 循環遍歷所有 H5 文件,加載數據到arr_all
  4. 創建唯一組 ID 的排序列表(第 0 列值)
  5. 根據 arr_all 中唯一行 ID 的數量和列的arr_all ,分配 arrays 以保存平均值/中值( arr_meanarr_median )。
  6. 循環 ID 列表中的值,然后:
    一種。 創建屏蔽數組 ( 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_list = sorted(set(arr_all[:,0]))

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) 

添加於 2022 年 11 月 22 日:
上面的方法使用了NumPy 1.10中引入的np.broadcast_to() 這是以前版本的替代方法。 (替換整個for i, row_val循環。)它應該更高效 memory 。 我還沒有配置文件來驗證,但是沒有創建 arrays all_maskma_arr_all

for i, row_val in enumerate(row_value_list):
    row_mask = np.where(col_0==row_val, False, True ) # True mask value ignores data.  
    for j in range(arr_all.shape[1]):
        masked_col = np.ma.masked_array(arr_all[:,j:j+1], mask=row_mask).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)

我使用 OP 提供的值運行。 下面提供了 Output,這兩種方法都相同:

Mean values:
 [[ 1.          3.          7.5       ]
 [ 2.          3.66666667  8.        ]
 [ 3.          4.66666667  9.        ]
 [ 4.          6.         12.        ]]
Median values:
 [[ 1.   3.   7.5]
 [ 2.   4.  10. ]
 [ 3.   6.  12. ]
 [ 4.   6.  12. ]]

暫無
暫無

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

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