【问题标题】:Optimize matrix to have the least number of rows with NaN优化矩阵以使 NaN 的行数最少
【发布时间】:2016-09-19 05:14:04
【问题描述】:

我有一个矩阵M。假设矩阵M 的每一行都是一个主题,每一列都是一个测量值。

M=rand(100);                % generate a 100x100 matrix random
c=randperm(length(M),100);  %select randomly 100 measurement indices
r=randperm(length(M),100);  %select randomly 100 subject indices

for i = 1 : 100
    M(r(i),c(i))=NaN;       % add randomly NaN. i.e. the subject c(i) does not have measurement c(i)
end

现在我删除所有受试者(如果有的话)缺少的测量值

idx_col_all_NAN = find(all(isnan(M)==1));   
M(:,idx_col_all_NAN)=[];

我删除了所有测量值都缺失的主题(如果有的话)

idx_row_all_NAN = find(all(isnan(M)==1,2));   
M(idx_row_all_NAN,:)=[];

现在我想删除测量值,以最大限度地增加具有相同测量值的受试者数量,并最大限度地减少包含 NaN 的 M 的单元格。

你能帮我吗?

【问题讨论】:

  • 因此,如果 2 个受试者(A 和 B)有一个具有相等值的测量值并且 A 在某个地方有一个 NaN,那么您希望将 NaN 替换为 B 的测量值,这是正确的吗?是否应该检查每个测量是否相等?
  • 只是为了让你知道:isnan(M) 会给你和isnan(M)==1 一样的结果。
  • @Finn 不,这不是我的意思...我不想替换任何值...只需找到最小化 NaN 数量的主题和测量值的组合
  • 所以删除所有在测量或主题中至少有一个 NaN 的主题和测量?
  • @Finn 原则上是的,但是使用真实数据我将删除所有主题:(

标签: matlab optimization matrix missing-data


【解决方案1】:

为了继续从矩阵中删除 NaN,您需要制定一些规则来最大限度地在更少数据和更少 NaN 之间进行权衡。正如您所说,如果您继续无限制地删除 NaN - 您可能会保留非常少量的数据。没有正确规则,这真的取决于你问什么,下面的建议只是让你知道如何处理这样的问题。

因此,作为起点,我定义了一个矩阵“质量”的索引,即矩阵中有多少“洞”:

M_ratio = sum(~isnan(M(:)))/numel(M); % the ratio between numbers to M size

随着矩阵中的数据越多,该索引将越大,如果没有 NaN,则它等于 1。只要我们看到改进,我们就可以继续从矩阵中删除行/列,但是因为只要剩下 NaN,矩阵就会变小,我们总是会看到改进,所以我们将留下空矩阵(或非常小的一个,取决于我们有多少 NaN)。

所以我们需要为改进定义一些阈值,这样如果删除没有在一定程度上改进矩阵 - 我们停止该过程:

improve = 1-M_old_ratio/M_new_ratio % the relative improvement after deletion

improve 是我们的“质量”索引中的相对增益,如果它不够大,我们将停止从矩阵中删除行/列。什么足够大?这很难说,但我会留给你玩,看看什么能给你带来不错的结果。

所以这里是完整的代码:

N = 100;
M = rand(N); % generate a NxN random matrix
M(randi(numel(M),N^2,1)) = nan;  % add NaN to randomly selected N^2 measurements
M(:,all(isnan(M)))=[]; % delete all NaN columns
M(all(isnan(M),2),:)=[]; % delete all NaN rows
threshold = 0.003; % the threshold for stop optimizing the matrix
while 1
    M_ratio = sum(~isnan(M(:)))/numel(M); % the ratio between numbers to M size
    [mincol,indcol] = min(sum(~isnan(M),1)); % find the column with most NaN
    [minrow,indrow] = min(sum(~isnan(M),2)); % find the row with most NaN
    [~,dir] = min([minrow;mincol]); % find which has more NaNs
    Mtry = M;
    if dir == 1
        Mtry(indrow,:) = []; % delete row
    else
        Mtry(:,indcol) = []; % delete column
    end
    Mtry_ratio = sum(~isnan(Mtry(:)))/numel(Mtry); % get the new ratio
    improve = 1-M_ratio/Mtry_ratio; % the relative improvement after deletion
    if improve>threshold % if it improves more than the threshold
        M = Mtry; % replace the matrix
    else
        break; % otherwise - quit
    end
end

如果你只考虑删除列而不是行,那就更简单了:

threshold = 0.002; % the threshold for stop optimizing the matrix
while 1
    M_ratio = sum(~isnan(M(:)))/numel(M); % the ratio between numbers to M size
    [~,indcol] = min(sum(~isnan(M),1)); % find the column with most NaN
    Mtry = M;
    Mtry(:,indcol) = []; % delete column
    Mtry_ratio = sum(~isnan(Mtry(:)))/numel(Mtry); % get the new ratio
    improve = 1-M_ratio/Mtry_ratio; % the relative improvement after deletion
    if improve>threshold % if it improves more than the threshold
        M = Mtry; % replace the matrix
    else
        break; % otherwise - quit
    end
end

您会注意到,我以更紧凑的方式将 NaN 引入矩阵,但这并不重要,因为您有一个真实数据。我还使用逻辑索引,这是一种更紧凑、更有效的删除列和行的方法。

【讨论】:

  • 感谢您的回答!如果矩阵 M 不是方阵,这会是一个偏差吗?我的意思是,例如,如果列多于行,它很可能会删除行..
  • @gabboshow 这取决于你认为什么是偏见。它计算的是nan 的数量,它试图最大化所有表中的数据/单元格比率。它将删除将带来最佳结果的行/列。它是一行还是一列真的取决于nan 在矩阵中的分布方式。同样,上述方法只是一种“思维方式”建议,您必须从您对数据的问题开始,并从中推断出处理缺失值的最佳方法是什么。也许您根本不需要删除它们...
猜你喜欢
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 2012-10-22
  • 2015-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多