为了继续从矩阵中删除 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 引入矩阵,但这并不重要,因为您有一个真实数据。我还使用逻辑索引,这是一种更紧凑、更有效的删除列和行的方法。