Вот один из способов использования первого алгоритма, который я мог придумать. Подход заключается в том, чтобы просто удалить строку или столбец в итерации, если в матрице есть хотя бы одно NA
и наименьшее количество не NA
значений (поэтому при удалении строки / столбца вы потеряете наименьшее количество ячеек). Чтобы сделать это, я создаю кадр данных для строк и столбцов с их счетами NA
и не- NA
вместе с измерением и индексом. В настоящий момент, если есть связь, она разрешается путем удаления строк перед столбцами и более ранних индексов до более поздних.
Я не уверен, что это даст глобальный максимум (например, занимает только одну ветвь при связях), но это должно быть лучше, чем просто удаление строк / столбцов. В этом примере мы получаем 210 для удаления строк, 74 для удаления столбцов, но 272 с новым подходом. Код также может быть оптимизирован, если вам нужно использовать его для гораздо больших матриц или для многих других NA
.
set.seed(1)
mat <- matrix(sample(x = c(1:10, NA), size = 37 * 21, replace = TRUE), ncol = 21)
# filter rows
prod(dim(mat[apply(mat, 1, function(x) all(!is.na(x))), ]))
#> [1] 210
# filter cols
prod(dim(mat[, apply(mat, 2, function(x) all(!is.na(x)))]))
#> [1] 74
delete_row_col <- function(m) {
to_delete <- rbind(
data.frame(
dim = "row",
index = seq_len(nrow(m)),
nas = rowSums(is.na(m)),
non_nas = rowSums(!is.na(m)),
stringsAsFactors = FALSE
),
data.frame(
dim = "col",
index = seq_len(ncol(m)),
nas = colSums(is.na(m)),
non_nas = colSums(!is.na(m)),
stringsAsFactors = FALSE
)
)
to_delete <- to_delete[to_delete$nas > 0, ]
to_delete <- to_delete[to_delete$non_nas == min(to_delete$non_nas), ]
if (nrow(to_delete) == 0) {
return(m)
}
else if (to_delete$dim[1] == "row") {
m <- m[-to_delete$index[1], ]
} else {
m <- m[, -to_delete$index[1]]
}
return(m)
}
remove_matrix_na <- function(m) {
while (any(is.na(m))) {
m <- delete_row_col(m)
}
return(m)
}
prod(dim(remove_matrix_na(mat)))
#> [1] 272
Создано в 2019-07-06 пакетом Представление (v0.3.0)