2014-01-27 36 views
1

我的数据是每三天一次,但在我的单元格阵列中,有时缺少日期。如何在矩阵添加日期时跳过一天并将NaN放入Sample Measurement单元格中?MATLAB根据日期列创建插入NaN的表格

下面是一个例子。我从这四个站点的每一个放了两条线。不同网站之间没有任何空行 - 它们只是为了清晰起见。

Latitude  Longitude SiteID   Date Local Sample Measurement 
43.435 -88.527778 027-0007 4/12/2007 4.3 
43.435 -88.527778 027-0007 4/15/2007 9.3 

43.060975 -87.913504 079-0026 4/12/2007 7.9 
43.060975 -87.913504 079-0026 4/15/2007 11.3 

45.203885 -90.60-8001 4/12/2007 3.3 
45.203885 -90.60-8001 4/18/2007 9.5 

43.020075 -88.21507 133-0027 4/12/2007 7.3 
43.020075 -88.21507 133-0027 4/18/2007 5.6 

下面是我想要的东西 - NaN的地方有几天没有。正如你所看到的,有不同的SiteID的,所以我需要可能做unique分开运行的网站。
纬度经度SITEID日期本地采样测量 43.435 -88.527778 027-0007 2007年4月12日4.3 43.435 -88.527778 027-0007 2007年4月15日9.3

43.060975 -87.913504 079-0026 4/12/2007 7.9 
43.060975 -87.913504 079-0026 4/15/2007 11.3 

45.203885 -90.60-8001 4/12/2007 3.3 
45.203885 -90.60-8001 4/15/2007 NaN 

43.020075 -88.21507 133-0027 4/12/2007 7.3 
43.020075 -88.21507 133-0027 4/15/2007 NaN 

我开始是这样的:

Set = datenum(2007,4,12):2:datenum(2007,10,15); 

B = cat(2,PM25data(:,1:2), PM25data(:,6), PM25data(:,12), PM25data(:,16)); % Pull out only the columns needed 
% B = {'Lat', 'Lon', 'SiteID', 'Date', 'Data'}; 
E = zeros(63, 5); 

i = 1; 
j = 1; 
k = 1; 
while i <= length(PM25site) && j <= length(E) && k <= length(B) % i = 1:4, j = 1:63, k = 1:32 

    if datenum(B(j,4)) ~= datenum(Set(j)) 
     C = datenum(Set(j)); 
     D = NaN; 
     E(j,:) = cat(2, str2double(B(j,1:3)), C, D); 
     j = j+1; 
    else 
     E(j,:) = str2double(B(k,:)); 
     k = k+1; 
     j = j+1; 
    end 
    E(:,3) = PM25site(i); 
    i = i+1; 

end 

此代码没有正确推进。它认为我没有正确编制索引,并且else不正确。它会放下我想要的东西,但只会替换前几行的零,然后一直保持零。

下面是一个例子部分:

45.203885 -90.60NaN 733144 3.3 
45.203885 -90.60NaN 733146 NaN 
45.203885 -90.60NaN 733148 NaN 
45.203885 -90.60NaN 733150 NaN 
0 0 0 0 0 
0 0 0 0 0 
0 0 0 0 0 
0 0 0 0 0 

我不知道这是接近它的最佳方式。我只是想在没有基于日期的数据的情况下添加NaN。

回答

1

我不认为你需要迭代while循环。它会很慢,而且不利用MATLAB的矩阵功能。这是我将如何去做的。

all_dates = datenum(2007,4,12):2:datenum(2007,10,15); 
% Note that we take the datenum of column 4 here now 
B = cat(2,PM25data(:,1:2), PM25data(:,6), datenum(PM25data(:,12)), PM25data(:,16)); 

% First, generate a list of all siteIDs 
[uID,ia] = unique(B(:,3)); 
% Now, preallocate the result matrix. 
% Use NaNs, since we will overwrite all non-nan values in the final matrix 
E = nan(length(all_dates)*length(uID),5); 

% Set the date column 
E(:,4) = repmat(all_dates,length(uID),1); 

% Set the lat, long and ID columns 
E(:,1) = reshape(repmat(B(ia,1)',length(all_dates),1),[],1); 
E(:,2) = reshape(repmat(B(ia,2)',length(all_dates),1),[],1); 
E(:,3) = reshape(repmat(uID',length(all_dates),1),[],1); 

% Find the columns which we have data for 
data_ind = ismember(E(:,3:4),B(:,3:4),'rows'); 
% And then set the data values 
E(data_ind,5) = B(:,5); 

大部分情况应该很清楚,但我只是澄清几点。

unique的第二个输出生成一个索引矩阵,它可以用来在原始矩阵中查找唯一结果。我们的意思是B(ia,3)生成所有唯一站点ID的列表。此外,B(ia,1)将生成这些siteID的纬度列表,同样也会生成经度。

重复所有日期的列表,与我们的siteID一样多次。基本上,我们确保我们有一个包含所有日期+ siteID组合的列表。

reshape(repmat(uID',length(all_dates),1),[],1)是一个整齐的小单行,将生成重复[1;1;1;2;2;2;3;3;3;...]而不是[1;2;3;1;2;3;1;2;3;...]重复的siteID列表。

最后,我们使用'rows'选项来获得ismember以搜索date和siteID的组合。使用这个,我们确定我们有数据的日期和siteID组合,并将这些数据复制到我们的最终矩阵中。我们没有数据的任何日期+ siteID将保留为NaN。

+0

但是,我仍然遇到麻烦,因为uID是一个单元格。 'E(:,3)'行出错,因为“从单元转换为双精度是不可能的”。由于siteID的格式为027-0007,因此如果转换为double,则无法保留,我不知道该怎么做。转换为字符串使他们成为4x8字符。帮帮我? – shizishan

+0

我试图用E代替你的代码。 – shizishan

+1

对不起,我应该已经意识到你的ID是单元而不是双单元。我的错!你可以做的一件事是有一个ID参考表,并将ID索引存储在'E'中,而不是实际的ID。例如'ID = [079-0026,025-0036,...];'这可以让你保持'E'为双重矩阵。如果'E'是一个单元格,它会变得更复杂一些。 – MrAzzaman