2016-12-27 106 views
3

我创建以下三维实体模型矩阵与NaN或Inf文件值:更换当满足某些条件

mockup(:,:,1) = ... 
    [100, 100, 100; ... 
    103, 95, 100; ... 
    101, 85, 100; ... 
    96, 90, 102; ... 
    91, 89, 99; ... 
    97, 91, 97; ... 
    105, 83, 100]; 

mockup(:,:,2) = ... 
    [50, NaN, NaN; ... 
    47, NaN, 40; ... 
    45, 60, 45; ... 
    47, 65, 45; ... 
    51, 70, 45; ... 
    54, 65, 50; ... 
    62, 80, 55]; 

我还定义percentTickerAvailable = 0.5

因此,各栏代表三种不同资产的股票价格。为了进一步处理,我需要按照以下方式操作NaN值。

  1. 如果任何给定行中NaN的百分比大于1 - percentTickerAvailable,则用NaN替换这些特定行中的所有值。也就是说,如果没有足够的资产在该行中具有价格,则完全忽略该行。
  2. 如果任何给定的ROW中NaN的百分比小于或等于1 - percentTickerAvailable,则用-inf替换各自的NaN。

要清楚的是,“任何给定行中的NaNs百分比”计算如下: 任何给定行中的NaN数量除以列数。

调整后的实体模型矩阵应该是这样的:

mockupAdj(:,:,1) = ... 
    [100, 100, 100; ... 
    103, 95, 100; ... 
    101, 85, 100; ... 
    96, 90, 102; ... 
    91, 89, 99; ... 
    97, 91, 97; ... 
    105, 83, 100]; 

mockupAdj(:,:,2) = ... 
    [NaN, NaN, NaN; ... 
    47, -inf, 40; ... 
    45, 60, 45; ... 
    47, 65, 45; ... 
    51, 70, 45; ... 
    54, 65, 50; ... 
    62, 80, 55]; 

到目前为止,我做了以下内容:

function vout = ranking(vin, percentTickerAvailable) 

percentNonNaN = 1 - sum(isnan(vin), 2)/size(vin, 2); 
NaNIdx = percentNonNaN < percentTickerAvailable; 
infIdx = percentNonNaN > percentTickerAvailable & ... 
    percentNonNaN < 1; 
[~, ~, numDimVin] = size(vin); 

for i = 1 : numDimVin 
    vin(NaNIdx(:,:,i) == 1, :, i) = NaN; 
end 

about = vin; 

end % EoF 

通过调用mockupAdj = ranking(mockup, 0.5)这已经正确地转换在第一行mockup(1,:,2){'NaN', 'NaN', 'NaN'}。但是,我正在努力解决第二点。用infIdx我已经成功识别出对应于第二个条件的行。但我不知道如何正确使用该信息来替换mockup(2,2,2)中的单个NaN与-inf

任何提示高度赞赏。

回答

3

1)

的NaN的任何给定行中的比例应小于1

...你说的是比例是多少?在这种情况下,这是无用的检查,因为情况总是如此。或者谈论百分比?在这种情况下,您的代码不会执行您所描述的内容。我的猜测是比例。 2)根据我的猜测,我有一个后续问题:跟着你的描述,不应该模型(2,2,2)留NaN?目前该行中的NaN的33%(< 50%),因此它不会满足基于我认为逻辑的答案你的条件2

3),我会相应地改变percentNaN = sum(isnan(vin), 2)/size(vin, 2);的可读性和NaNIdx = percentNaN > percentTickerAvailable;。现在只需在循环前添加一行:

vin(isnan(vin)) = -inf; 

为什么?因为像这样你用-inf替换所有的NaN。之后,方面1的那些将被循环覆盖到NaN上。您不需要InfIdx。 4)请注意,你的函数现在还不能返回vout。让它返回vin,你会没事的。

+0

莱昂内尔,你有点正确。我混淆了这两个条件。我编辑了我原来的帖子。 – Andi

+0

告诉我,如果我的解决方案适合你:) 我在我的测试它,它的工作原理! 只需保留您的代码并添加一行即可! –

4

这是一个很好的例子,可以使用矢量化来解决。我提供了两种版本的代码,一种使用现代语法(包括隐式扩展),另一种使用老版本的MATLAB。

有几件事情需要注意:

  • NaN替代阶段,我用其中0/0进行评估,以NaN一个“绝招”。
  • Inf替换阶段,我使用逻辑掩码/索引来访问vin中的正确元素。

R2016b和更新:

function vin = ranking (vin, percentTickerAvailable) 
    % Find percentage of NaNs on each line: 
    pNaN = mean(isnan(vin), 2, 'double'); 
    % Fills rows with NaNs: 
    vin = vin + 0 ./ (1 - (pNaN >= percentTickerAvailable)); 
    % Replace the rest with -Inf 
    vin(isnan(vin) & pNaN < percentTickerAvailable) = -Inf; 
end 

此前R2016b:

function vin = rankingOld (vin, percentTickerAvailable) 
    % Find percentage of NaNs on each line: 
    pNaN = mean(isnan(vin), 2, 'double'); 
    % Fills rows with NaNs: 
    vin = bsxfun(@plus, vin, 0 ./ (1 - (pNaN >= percentTickerAvailable))); 
    % Replace the rest with -Inf 
    vin(bsxfun(@and, isnan(vin), pNaN < percentTickerAvailable)) = -Inf; 
end 
1

您也可以使用逻辑索引来实现这一任务:

x(:,:,1) = ... 
    [100, 100, 100; ... 
    103, 95, 100; ... 
    101, 85, 100; ... 
    96, 90, 102; ... 
    91, 89, 99; ... 
    97, 91, 97; ... 
    105, 83, 100]; 

x(:,:,2) = ... 
    [50, NaN, NaN; ... 
    47, NaN, 40; ... 
    45, 60, 45; ... 
    47, 65, 45; ... 
    51, 70, 45; ... 
    54, 65, 50; ... 
    62, 80, 55]; 

    % We fix the threshold 
    tres = 0.5; %fix the threshold. 

    % We check if a value = NaN or not. 
    in = isnan(x); 
    % Which line have more than 50% of NaN ?. 
    ind = (sum(in,2)./(size(x,2)))>0.5 
    % We generate an index 
    [x1,~,x3] = ind2sub(size(ind),ind); 
    % We set the NaN index to 0 if the line contains less than 50 % of NaN. 
    in(x1,:,x3) = 0; 

    % We calculate the new values. 
    x(in) = -inf; 
    x(x1,:,x3) = NaN; 
相关问题