2017-10-11 398 views
3

我正在寻找方法,内置函数,最佳实践...将新数据追加到矩阵 - 当行和列不相同时 - 在Matlab中添加新数据的高效方法(使用示例代码)

我处理的结构为数据如下:

A.values: Ta x Ma matrix of values 
A.dates: Ta x 1 vector of datenum 
A.id:  1 x Ma cell array of ids 

现在面临的挑战是如何处理,我加载和想追加到一个新的矩阵新的(可能重叠的)数据BC

当有新的数据进来,它可以扩大水平和垂直方向由于:

  • 新的ID
  • 新日期

它也可以有以前min(A.dates)开始日期max(A.dates)之间min(A.dates)max(A.dates)。 ID可以全部在B中独一无二(全新),或者一些可以重叠。

下面是一个例子:

A.values = [2.1 2.4 2.5 2.6; ... 
      4.1 4.4 4.5 4.6; ... 
      6.1 6.4 6.5 6.6]; 
A.dates = [730002; ... 
      730004; ... 
      730006]; 
A.id  = {'x1', 'x4', 'x5', 'x6'}; 

现在,新的数据进来:

B.values = [1.2 1.9 1.5 1.6 1.7; ... 
      3.2 3.9 3.5 3.6 3.7; ... 
      7.2 7.9 7.5 7.6 7.7; ... 
      8.2 8.9 8.5 8.6 8.7]; 
B.dates = [730001; ... 
      730003; ... 
      730007; ... 
      730008]; 
B.id  = {'x2', 'x9', 'x5', 'x6', 'x7'}; 

我们现在怎么办高效,快速地构建新的结构C

C.values = [NaN 1.2 NaN 1.5 1.6 1.7 1.9; ... 
      2.1 NaN 2.4 2.5 2.6 NaN NaN; ... 
      NaN 3.2 NaN 3.5 3.6 3.7 3.9; ... 
      4.1 NaN 4.4 4.5 4.6 NaN NaN; ... 
      6.1 NaN 6.4 6.5 6.6 NaN NaN; ... 
      NaN 7.2 NaN 7.5 7.6 7.7 7.9; ... 
      NaN 8.2 NaN 8.5 8.6 8.7 8.9]; 
C.dates = [730001; ... 
      730002; ... 
      730003; ... 
      730004; ... 
      730006; ... 
      730007; ... 
      730008]; 
C.id  = {'x1', 'x2', 'x4', 'x5', 'x6', 'x7', 'x9'}; 

更新与时间表

继意见,我试着用timetable实现这一目标如下:

function dfmerged = in_mergeCache(dfA, dfB) 

dtA = datenum2datetime(dfA.dates); % function datenum2datetime can be found here: https://stackoverflow.com/a/46685634/4262057 
dtB = datenum2datetime(dfB.dates); 

TTa = array2timetable(dfA.values, 'RowTimes', dtA, 'VariableNames', dfA.id); 
TTb = array2timetable(dfB.values, 'RowTimes', dtB, 'VariableNames', dfB.id); 

TTs = synchronize(TTa,TTb); 

dfmerged.id  = TTs.Properties.VariableNames; 
dfmerged.values = table2array(TTs); 
dfmerged.dates = datenum(TTs.Time); %to convert datenum 

end 

问题:但是,这给了我一个很大的时间表,其中行确实同步的行,但只是重复的列(9列)。我怎样才能同步列?

C = 

    struct with fields: 

     id: {'x1' 'x4' 'x5_TTa' 'x6_TTa' 'x2' 'x9' 'x5_TTb' 'x6_TTb' 'x7'} 
    values: [7×9 double] 
    dates: [7×1 double] 
+0

哪个版本的MATLAB您使用的是?从2016b开始,你可以使用'timetable'对象和'synchronize'这样的东西 – Wolfie

+0

啊发现了:)这样的例子在上面会怎么样呢?我必须在时间表中改变一切吗?这不会花费很多时间吗? – JohnAndrews

+0

您可以将数据存储在表格中,无需更改代码,因为表格变量可以使用点符号与结构相同的方式进行访问,但事情可能会更简单;鉴于您基本上拥有标题和行数据的表格结构 – Wolfie

回答

1

下面是一个解决方案使用unique和索引:

%combine the data and take unique value of them + their index 
[C.id,~,date_i] = unique([A.dates(:);B.dates(:)]); 
[C.dates,~,id_i] = unique([A.id B.id]); 

C.values = nan(numel(C.dates),numel(C.id)); 
%use matrix indexing to fill the sub-materices corresponding to elements of A and B 
C.values(date_i(1:numel(A.dates)),id_i(1:numel(A.id)))=A.values; 
C.values(date_i(numel(A.dates)+1:end),id_i(numel(A.id)+1:end))=B.values; 
+0

AB不会工作,因为它们可能有不同的行数。 A和B的行数和列数是不同的。 – JohnAndrews

+0

数值范围是从“1.1”到“9.9”吗? – rahnema1

+0

不,他们总是改变。请参阅示例A和B.预先未知行数。列数也可能不同。所以我们需要同时进行水平和垂直同步。 – JohnAndrews