Случайным образом удалить некоторые числовые данные из матрицы в R?

#r #random

Вопрос:

У меня есть большая матрица данных со многими числовыми значениями (числами) в ней. Я хотел бы удалить 10% всех подсчетов. Так, например, матрица, которая выглядит следующим образом:

 30 10  0 20  

Сумма всех подсчетов здесь равна 60. 10% от 60 — это 6. Поэтому я хочу случайным образом удалить 6. Правильный вывод может быть:

 29 6  0 19  

(Как вы можете видеть, он удалил 1 из 30, 4 из 10 и 1 из 20). Не может быть отрицательных значений.

Как я мог запрограммировать это в R?

Ответ №1:

Вот способ. Он вычитает от 1 до положительных элементов матрицы до тех пор, пока не будет достигнуто определенное общее количество удаляемых элементов.

 subtract_int lt;- function(X, n){  inx lt;- which(X != 0, arr.ind = TRUE)  N lt;- nrow(inx)  while(n gt; 0){  i lt;- sample(N, 1)  if(X[ inx[i, , drop = FALSE] ] gt; 0){  X[ inx[i, , drop = FALSE] ] lt;- X[ inx[i, , drop = FALSE] ] - 1  n lt;- n - 1  }  if(any(X[inx] == 0)){  inx lt;- which(X != 0, arr.ind = TRUE)  N lt;- nrow(inx)  }  }  X }  set.seed(2021) to_remove lt;- round(sum(A)*0.10) subtract_int(A, to_remove) # [,1] [,2] #[1,] 30 6 #[2,] 0 18  

Данные

 A lt;- structure(c(30, 0, 10, 20), .Dim = c(2L, 2L))  

Ответ №2:

Может быть, это поможет вам, по крайней мере, встать на правильный путь. Хотя это не более чем черновик:

 randomlyRemove lt;- function(matrix) {  sum_mat lt;- sum(matrix)  while (sum_mat gt; 0) {  sum_mat lt;- sum_mat - runif(1, min = 0, max = sum_mat)  x lt;- round(runif(1, 1, dim(matrix)[1]), digits = 0)  y lt;- round(runif(1, 1, dim(matrix)[2]), digits = 0)    matrix[x,y] lt;- matrix[x,y] - sum_mat  }  return(matrix) }  

Возможно, вам захочется поиграть с процессом генератора случайных чисел, чтобы получить более равномерно распределенные вычитания.

правка: добавлен раунд(цифры = 0), чтобы получать только целочисленные (размерные) значения, и изменено генерация случайных (размерных) значений, чтобы начинаться с 1 (не с нуля).

Ответ №3:

Я думаю, мы сможем заставить его работать с помощью sample . Это решение намного компактнее.

Данные

 A lt;- structure(c(30, 0, 11, 20), .Dim = c(2L, 2L)) sum(A) #gt; [1] 61  

Логика

 UseThese lt;- (1:length(A))[A gt; 0] # Choose indices to be modified because gt; 0 Sample lt;- sample(UseThese, sum(A)*0.1, replace = TRUE) # Draw a sample of indices A[UseThese] lt;- A[UseThese] - as.vector(table(Sample)) # Subtract handling repeated duplicate indices in the sample  

Проверьте результат

 A #gt; [,1] [,2] #gt; [1,] 28 8 #gt; [2,] 0 19 sum(A) # should be the value above minus 6 #gt; [1] 55  

Одним из недостатков этого решения является то, что оно может привести к отрицательным значениям. Так что сверьтесь с:

 any(A lt; 0) #gt; [1] FALSE