根据MATLAB中的几个索引将数据分配给矩阵
Allocating data to a matrix according to several indices in MATLAB
考虑以下矩阵,其中第一列是时间索引,第二列和第三列包含数据。
Data=
1 5 100
2 10 100
3 5 300
4 15 200
5 5 500
6 15 0
7 10 400
8 5 300
9 10 200
10 10 0
11 5 300
12 10 100
13 15 1000
... ... ...
T ... ...
这些数据可能被认为是拍卖或交换单一商品的订单,其中在每个时间点 t(第 1 列)都有 "price"(第 2 列)的新订单到达并且 total 在此特定时间点按此价格需求的单位数量在第 3 列中。因此,例如,考虑买家提交商品出价的拍卖,则上述数据意味着:
第 1 行: 在时间 t=1 新订单到达,该订单的价格为 5,在此价格下需求的总单位数为 100。
第 2 行: 在时间 t=2 ... 价格为 10 的订单 - 价格为 10 的总需求为 100
总结:在时间 t=2,价格 5 需要 100 个单位,价格 10 需要 100 个
第 3 行: 在时间 3 ... 价格为 5 的订单需要 额外 200 件,所以总件数价格 5 的需求是 300
总结:在时间 t=3,价格 5 需要 300 件,价格 10 需要 100 件
第 4 行: t=4 ... 以价格 15 订购 200 件,价格 15 的总需求量为 200
总结:t=4 价格为 5 时需要 300 个单位,价格为 10 时需要 100 个,价格为 15 时需要 200 个
...
总结:t=5 价格为 5 时需要 500 件,价格为 10 时需要 100 件,价格为 15 时需要 200 件
第6行: t=6 价格为15但第三列有0个单位,表示订单被取消,价格15没有需求
总结:t=6 价格 5 需要 500 件,价格 10 需要 100 件
我想将数据分配给以下两个Tx3矩阵,其中每一行代表上面的“Summary:”行:
[Price=5][Price = 10][Price = 15]
[Time = 1] 5 NaN NaN
[Time = 2] 5 10 NaN
[Time = 3] 5 10 NaN
[Time = 4] 5 10 15
[Time = 5] 5 10 15
[Time = 6] 5 10 NaN
[Time = 7] 5 10 NaN
[Time = 8] 5 10 NaN
[Time = 9] 5 10 NaN
[Time = 10] 5 NaN NaN
[Time = 11] 5 NaN NaN
[Time = 12] 5 10 NaN
[Time = 13] 5 10 15
... ... ... ...
[Time = T] ... ... ...
[Price=5][Price = 10][Price = 15]
[Time = 1] 100 NaN NaN
[Time = 2] 100 100 NaN
[Time = 3] 300 100 NaN
[Time = 4] 300 100 200
[Time = 5] 500 100 200
[Time = 6] 500 100 NaN
[Time = 7] 500 400 NaN
[Time = 8] 300 400 NaN
[Time = 9] 300 200 NaN
[Time = 10] 300 NaN NaN
[Time = 11] 300 NaN NaN
[Time = 12] 300 100 NaN
[Time = 13] 300 100 1000
... ... ... ...
[Time = T] ... ... ...
基本上,上面的两个矩阵可以让我得到 "time" 的任何一点的 "prices" 和 "units"。请注意,每个 "price" 可能有不连续性,一旦 "units" 为 0 就会出现 - 因此 "price=15" 仅出现在 t=4 并且仅存在两个时期:t=4,t=5 (订单在 t=6 取消)在 t=13 再次出现。
我进行如下处理:
1.) 按第 2 列 ("prices") 对数据矩阵进行排序,并获取第 2 列中唯一值的索引:
Data=sortrows(Data, [2 1]);
[~,~, IndexPrice]=unique(Data(:,2));
Data= IndexPrice=
1 5 100 1
3 5 300 1
5 5 500 1
8 5 300 1
11 5 300 1
2 10 100 2
7 10 400 2
9 10 200 2
10 10 0 2
12 10 100 2
4 15 200 3
6 15 0 3
13 15 1000 3
... ... ... ...
T ... ... ...
2.) 为两个输出矩阵分配值:
OutputPrice=NaN(size(Data,1), max(IndexPrice)); %Preallocate matrix
for j=1:max(IndexPrice) %Go column-wise
TempData=Data(IndexPrice==j,:); %Submatrix for unique "price"
for i=1:size(TempData,1)
if TempData(i,3)~=0 %Check for discontinuity (0 in col 3)
OutputPrice(TempData(i,1):end,j)=TempData(1,2); %Fill wiht values
else
OutputPrice(TempData(i,1):end,j)=NaN; % If there is 0 fill with NaNs
end
end
end
OutputUnits=NaN(size(Data,1), max(IndexPrice));
for j=1:max(IndexPrice)
TempData=Data(IndexPrice==j,:);
for i=1:size(TempData,1)
if TempData(i,3)~=0
OutputUnits(TempData(i,1):end,j)=TempData(i,3); %The "units" change in contrast to the "prices"
else
OutputUnits(TempData(i,1):end,j)=NaN;
end
end
end
当然,关键是代码的性能 - 它似乎是解决问题的 "brute force" 方法。如果有任何关于更有效的解决方法的建议,我将不胜感激。
我不认为这个版本比你的更清楚,但它是对数线性的而不是二次的,所以它会显示大型数据集的性能改进。这个想法是为每个价格构建一个向量,该向量具有与 Data
相同的行数,并且每个条目将给出最后一次以该价格订购某物的价值。这是行 posOfDemands(idxLastDemand(hasLastDemand))
。 [顺便说一句:这实际上是对您的 earlier questions] 之一的回答。在您的 price==5
示例中,这将产生向量
[1 1 3 3 5 5 5 8 8 8 11 11 11]
。使用这个向量,我们得到最后一个 demands
/prices
,然后如果它们为零,则只需用 NaN
替换它们:
%%// Rename the variables
prices = Data(:,2);
demands = Data(:,3);
%%// Find number of different prices
uniquePrices = unique(prices);
nUniquePrices = length(uniquePrices);
nData = size(prices,1);
[OutputUnits, OutputPrices] = deal(zeros(nData,nUniquePrices));
%%// For each price do:
for i = 1:nUniquePrices
%%// Find positions of all demands
posOfDemands = find(prices==uniquePrices(i));
idxLastDemand = cumsum(prices==uniquePrices(i));
hasLastDemand = idxLastDemand~=0;
%%// Get the values of the last demands/prices
OutputUnits(hasLastDemand,i) = demands(posOfDemands(idxLastDemand(hasLastDemand)));
OutputPrices(hasLastDemand,i) = prices(posOfDemands(idxLastDemand(hasLastDemand)));
end
%%// Convert 0s to NaNs
OutputPrices(OutputUnits == 0) = NaN;
OutputUnits(OutputUnits == 0) = NaN;
矢量化版本:
这是一个速度更快的矢量化版本:
prices = Data(:,2);
demands = Data(:,3);
uniquePrices = unique(prices);
nUniquePrices = length(uniquePrices);
%%// Introduce leading demands of value 0 to get the zeros in the beginning
isDemanded = [true(1,nUniquePrices); bsxfun(@eq, prices, uniquePrices.')];
demands = [0; demands];
%%// Find positions of all demands
[rowOfDemands,ignore_] = find(isDemanded);
idxLastDemand = reshape(cumsum(isDemanded(:)),[],nUniquePrices);
%%// Get the values of the last demands/prices
OutputUnits = demands(rowOfDemands(idxLastDemand(2:end,:)));
OutputUnits(OutputUnits == 0) = NaN;
OutputPrices = ones(size(OutputUnits,1),1)*uniquePrices(:).';
OutputPrices(isnan(OutputUnits)) = NaN;
考虑以下矩阵,其中第一列是时间索引,第二列和第三列包含数据。
Data=
1 5 100
2 10 100
3 5 300
4 15 200
5 5 500
6 15 0
7 10 400
8 5 300
9 10 200
10 10 0
11 5 300
12 10 100
13 15 1000
... ... ...
T ... ...
这些数据可能被认为是拍卖或交换单一商品的订单,其中在每个时间点 t(第 1 列)都有 "price"(第 2 列)的新订单到达并且 total 在此特定时间点按此价格需求的单位数量在第 3 列中。因此,例如,考虑买家提交商品出价的拍卖,则上述数据意味着:
第 1 行: 在时间 t=1 新订单到达,该订单的价格为 5,在此价格下需求的总单位数为 100。
第 2 行: 在时间 t=2 ... 价格为 10 的订单 - 价格为 10 的总需求为 100
总结:在时间 t=2,价格 5 需要 100 个单位,价格 10 需要 100 个
第 3 行: 在时间 3 ... 价格为 5 的订单需要 额外 200 件,所以总件数价格 5 的需求是 300
总结:在时间 t=3,价格 5 需要 300 件,价格 10 需要 100 件
第 4 行: t=4 ... 以价格 15 订购 200 件,价格 15 的总需求量为 200
总结:t=4 价格为 5 时需要 300 个单位,价格为 10 时需要 100 个,价格为 15 时需要 200 个
...
总结:t=5 价格为 5 时需要 500 件,价格为 10 时需要 100 件,价格为 15 时需要 200 件
第6行: t=6 价格为15但第三列有0个单位,表示订单被取消,价格15没有需求
总结:t=6 价格 5 需要 500 件,价格 10 需要 100 件
我想将数据分配给以下两个Tx3矩阵,其中每一行代表上面的“Summary:”行:
[Price=5][Price = 10][Price = 15]
[Time = 1] 5 NaN NaN
[Time = 2] 5 10 NaN
[Time = 3] 5 10 NaN
[Time = 4] 5 10 15
[Time = 5] 5 10 15
[Time = 6] 5 10 NaN
[Time = 7] 5 10 NaN
[Time = 8] 5 10 NaN
[Time = 9] 5 10 NaN
[Time = 10] 5 NaN NaN
[Time = 11] 5 NaN NaN
[Time = 12] 5 10 NaN
[Time = 13] 5 10 15
... ... ... ...
[Time = T] ... ... ...
[Price=5][Price = 10][Price = 15]
[Time = 1] 100 NaN NaN
[Time = 2] 100 100 NaN
[Time = 3] 300 100 NaN
[Time = 4] 300 100 200
[Time = 5] 500 100 200
[Time = 6] 500 100 NaN
[Time = 7] 500 400 NaN
[Time = 8] 300 400 NaN
[Time = 9] 300 200 NaN
[Time = 10] 300 NaN NaN
[Time = 11] 300 NaN NaN
[Time = 12] 300 100 NaN
[Time = 13] 300 100 1000
... ... ... ...
[Time = T] ... ... ...
基本上,上面的两个矩阵可以让我得到 "time" 的任何一点的 "prices" 和 "units"。请注意,每个 "price" 可能有不连续性,一旦 "units" 为 0 就会出现 - 因此 "price=15" 仅出现在 t=4 并且仅存在两个时期:t=4,t=5 (订单在 t=6 取消)在 t=13 再次出现。
我进行如下处理:
1.) 按第 2 列 ("prices") 对数据矩阵进行排序,并获取第 2 列中唯一值的索引:
Data=sortrows(Data, [2 1]);
[~,~, IndexPrice]=unique(Data(:,2));
Data= IndexPrice=
1 5 100 1
3 5 300 1
5 5 500 1
8 5 300 1
11 5 300 1
2 10 100 2
7 10 400 2
9 10 200 2
10 10 0 2
12 10 100 2
4 15 200 3
6 15 0 3
13 15 1000 3
... ... ... ...
T ... ... ...
2.) 为两个输出矩阵分配值:
OutputPrice=NaN(size(Data,1), max(IndexPrice)); %Preallocate matrix
for j=1:max(IndexPrice) %Go column-wise
TempData=Data(IndexPrice==j,:); %Submatrix for unique "price"
for i=1:size(TempData,1)
if TempData(i,3)~=0 %Check for discontinuity (0 in col 3)
OutputPrice(TempData(i,1):end,j)=TempData(1,2); %Fill wiht values
else
OutputPrice(TempData(i,1):end,j)=NaN; % If there is 0 fill with NaNs
end
end
end
OutputUnits=NaN(size(Data,1), max(IndexPrice));
for j=1:max(IndexPrice)
TempData=Data(IndexPrice==j,:);
for i=1:size(TempData,1)
if TempData(i,3)~=0
OutputUnits(TempData(i,1):end,j)=TempData(i,3); %The "units" change in contrast to the "prices"
else
OutputUnits(TempData(i,1):end,j)=NaN;
end
end
end
当然,关键是代码的性能 - 它似乎是解决问题的 "brute force" 方法。如果有任何关于更有效的解决方法的建议,我将不胜感激。
我不认为这个版本比你的更清楚,但它是对数线性的而不是二次的,所以它会显示大型数据集的性能改进。这个想法是为每个价格构建一个向量,该向量具有与 Data
相同的行数,并且每个条目将给出最后一次以该价格订购某物的价值。这是行 posOfDemands(idxLastDemand(hasLastDemand))
。 [顺便说一句:这实际上是对您的 earlier questions] 之一的回答。在您的 price==5
示例中,这将产生向量
[1 1 3 3 5 5 5 8 8 8 11 11 11]
。使用这个向量,我们得到最后一个 demands
/prices
,然后如果它们为零,则只需用 NaN
替换它们:
%%// Rename the variables
prices = Data(:,2);
demands = Data(:,3);
%%// Find number of different prices
uniquePrices = unique(prices);
nUniquePrices = length(uniquePrices);
nData = size(prices,1);
[OutputUnits, OutputPrices] = deal(zeros(nData,nUniquePrices));
%%// For each price do:
for i = 1:nUniquePrices
%%// Find positions of all demands
posOfDemands = find(prices==uniquePrices(i));
idxLastDemand = cumsum(prices==uniquePrices(i));
hasLastDemand = idxLastDemand~=0;
%%// Get the values of the last demands/prices
OutputUnits(hasLastDemand,i) = demands(posOfDemands(idxLastDemand(hasLastDemand)));
OutputPrices(hasLastDemand,i) = prices(posOfDemands(idxLastDemand(hasLastDemand)));
end
%%// Convert 0s to NaNs
OutputPrices(OutputUnits == 0) = NaN;
OutputUnits(OutputUnits == 0) = NaN;
矢量化版本:
这是一个速度更快的矢量化版本:
prices = Data(:,2);
demands = Data(:,3);
uniquePrices = unique(prices);
nUniquePrices = length(uniquePrices);
%%// Introduce leading demands of value 0 to get the zeros in the beginning
isDemanded = [true(1,nUniquePrices); bsxfun(@eq, prices, uniquePrices.')];
demands = [0; demands];
%%// Find positions of all demands
[rowOfDemands,ignore_] = find(isDemanded);
idxLastDemand = reshape(cumsum(isDemanded(:)),[],nUniquePrices);
%%// Get the values of the last demands/prices
OutputUnits = demands(rowOfDemands(idxLastDemand(2:end,:)));
OutputUnits(OutputUnits == 0) = NaN;
OutputPrices = ones(size(OutputUnits,1),1)*uniquePrices(:).';
OutputPrices(isnan(OutputUnits)) = NaN;