2017-06-01 36 views
1

我有三年的數據矩陣十年(2001-2010)。在每個文件數據矩陣中是180 x 360 x 365/366(緯度x經度x每日降雨量)。例如:2001:180x360x365,2002:180x360x365,2003:180x360x365,2004:180x360x366 ........................... 2010:180x360x365如何將三維日常數據轉換爲每月?

現在我想將這個每日降雨量轉換成月降雨量(通過求和)並將所有年份合併到一個文件中。所以我最終的輸出將是180x360x120(緯度x經度x十年的月降雨量)。

+0

這個最大的問題是個月的非均勻性(它們具有不同的量天) –

+0

是,在時間段2004年和2008年是閏年。 – SONY

回答

0

我相信你可以通過矢量化來更快地工作,但它應該完成這項工作。沒有正確測試

% range of years 
years = 2000:2016; 
leap_years = [2000 2004 2008 2012 2016]; 

% Generating random data 
nr_of_years = numel(years); 
rainfall_data = cell(nr_of_years, 1); 
for i=1:nr_of_years 
    nr_of_days = 365; 
    if ismember(years(i), leap_years); 
     nr_of_days = 366; 
    end 
    rainfall_data{i} = rand(180, 360, nr_of_days); 
end 

你需要的實際代碼如下

% fixed stuff 
months = 12; 
nr_of_days = [31 28 31 30 31 30 31 31 30 31 30 31]; 
nr_of_days_leap = [31 29 31 30 31 30 31 31 30 31 30 31]; 

% building vectors of month indices for days 
month_indices = []; 
month_indices_leap = []; 
for i=1:months 
    month_indices_temp = repmat(i, nr_of_days(i), 1); 
    month_indices_leap_temp = repmat(i, nr_of_days_leap(i), 1); 
    month_indices = [month_indices; month_indices_temp]; 
    month_indices_leap = [month_indices_leap; month_indices_leap_temp]; 
end 

% the result will be stored here 
result = zeros(size(rainfall_data{i}, 1), size(rainfall_data{i}, 2), months*nr_of_years); 

for i=1:nr_of_years 
    % determining which indices to use depending if it is a leap year 
    month_indices_temp = month_indices; 
    if size(rainfall_data{i}, 3)==366 
     month_indices_temp = month_indices_leap; 
    end 

    % data for the current year 
    current_data = rainfall_data{i}; 
    % this holds the data for current year 
    monthy_sums = zeros(size(rainfall_data{i}, 1), size(rainfall_data{i}, 2), months); 
    for j=1:months 
     monthy_sums(:,:,j) = sum(current_data(:,:,j==month_indices_temp), 3); 
    end 
    % putting it into the combined matrix 
    result(:,:,((i-1)*months+1):(i*months)) = monthy_sums; 
end 

可以使用建立datetimedatestrdatenum可能實現更完美的解決方案,但我不知道那些會要快很多或更短。

編輯:另一種使用內置的日期函數

months = 12; 
% where the result will be stored 
result = zeros(size(rainfall_data{i}, 1), size(rainfall_data{i}, 2), months*nr_of_years); 
for i=1:nr_of_years 
    current_data = rainfall_data{i}; 
    % first day of the year 
    year_start_timestamp = datenum(datetime(years(i), 1, 1)); 

    % holding current sums 
    monthy_sums = zeros(size(current_data, 1), size(current_data, 2), months); 

    % finding the month indices vector 
    datetime_obj = datetime(datestr(year_start_timestamp:(year_start_timestamp+size(current_data, 3)-1))); 
    month_indices = datetime_obj.Month; 

    % summing 
    for j=1:months 
     monthy_sums(:,:,j) = sum(current_data(:,:,j==month_indices), 3); 
    end 

    % result 
    result(:,:,((i-1)*months+1):(i*months)) = monthy_sums; 
end 

這第二個解決了1.45秒對我來說,相比於1.2秒,第一個解決方案。兩種情況的結果都是一樣的。希望這可以幫助。

0

這可能是耗時的,但我想你可以使用某種形式的循環遍歷數據每年每月的基礎上,挑選出的數據點的適當數量的每個月,然後添加到最終的數據集。下面的東西(非常粗糙)代碼的效果可能的工作:

years = ['2001','2002,'2003',...,'2010']; 

months = ['Jan','Feb','Mar',...,'Dec']; 

finalDataset=[]; 
for i=1:length(years) 
    year = years(i); 
    yearData=%% load in dataset for that year %% 
    for j=1:length(months) 
     month = months(j); 
     switch month 
      case {'Jan','Mar'} 
        days=30; 
      case 'Feb' 
        days=28' 
        if(year=='2004' || year=='2008') 
        days=29; 
        end 
       % then continue with cases to include each month 
     end 
     monthData=yearData(:,:,1:days) % extract the data for those months 
     yearData(:,:,1:days)=[]; % delete data already extracted 
     summedRain = % take mean of rainfall data 
     monthSummed = % replace daily rainfall data with monthly rainfall, but keep latitude and longitude data 
     finalDataset=[finalDataset; monthSummed]; 
     end 
    end 

道歉,這是非常簡陋的,我還沒有包括一些索引的細節,但我希望至少說明一個想法,可以幫助?我也不完全確定「轉換」語句中的「if」語句是否有效,但如果沒有,可以在其他地方添加修改日期。

相關問題