基于另一个矩阵的值在矩阵中提取值,而在Octave中没有for循环

时间:2014-01-17 17:02:09

标签: matlab for-loop matrix octave vectorization

我想知道是否有办法对一个矩阵的值进行操作,分别基于另一个矩阵的每一行的值,而不使用for循环。

以下一个具体示例。

data是一个~500k的行矩阵,有三列:第一列是小时/日期列表(我将它们作为序列号),每天24小时覆盖数年,第二列是一个位置ID,第三个是该地区的电费。

hours有两列:第一列是日期/小时列表作为序列号,第二列是特定于该小时的特定上限。

我需要做的是,hours中的每个日期和小时,找到低于hours中设置的上限的最大电费成本,并保存相应的ID如果hours是唯一的,则在id的第三列中的位置;如果没有满足条件的位置或者多于一个的位置,则为零。

我正在使用的代码的简化版本:

#Add a third column for the hours matrix
ids=zeros(rows(hours),1)
hours=horzcat(hours,ids)


for i=1:rows(hour)
  #Get the data for all locations in that hour
  idx=(data(:,1)==hour(i,1) )   
  hourlydata=(data(idx,:))        

  #Get the ID for the maximum below the limit in that hour
  idx=(hourlydata(:,3)<hour(i,2))
  idlimit=(hourlydata(idx,3)==max(hourlydata(idx,3))   

  dataid=hourlydata(idlimit,2)

  #Check if the data exists and is unique
  if(rows(dataid)==1)
     id=dataid(1,1)
  else
     id=0
  endif  

  #Save the ID
  hour(i,3)=id
endfor

有没有办法在不使用for循环的情况下执行此操作?

(我已经优化了data矩阵,使其尽可能小,但它仍然很大,所以在尝试实现解决方案时可能会遇到内存限制)

1 个答案:

答案 0 :(得分:0)

您可以使用arrayfun。假设您的数据是

data = [datenum('2014-01-17'), 1, 13;datenum('2014-01-18'), 2, 7]
hours = [datenum('2014-01-17'), 17; datenum('2014-01-18'), 3]

然后定义选择器功能

function id = select( d, limit, data )
  idx = (data(:,1)==d );

  hourlydata = (data(idx,:));

  idx = (hourlydata(:,3)<limit);
  idlimit = (hourlydata(idx,3)==max(hourlydata(idx,3)));   

  dataid=hourlydata(idlimit,2);

  if length(dataid)==1
     id=dataid(1,1)
  else
     id=0
  end

end

现在我们找到一个与包含id

的小时相同的向量
arrayfun(@(d, limit) select(d, limit, data), hours(:,1), hours(:,2))
ans =
 1
 0

您可以轻松地将此向量合并数小时。

现在我怀疑这更快,但没有循环。与MATLAB一起使用,未使用Octave进行检查。