Выбор n% процентов элементов из строк матрицы, различное количество элементов в каждой строке - PullRequest
0 голосов
/ 05 июля 2018

У меня проблема с выбором n% самых больших и самых маленьких элементов из каждой строки матрицы данных. В частности, я хотел бы найти номера столбцов этих верхних n% элементов. Это не было бы проблемой, если бы в каждой строке было одинаковое количество не-NA-элементов, но в этой ситуации количество выбранных элементов отличается для каждой строки. Вот пример ситуации (реальная матрица данных - 195x1030, поэтому я не буду использовать ее здесь), где выбираются 40% верхних

data=     
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1   NA   100  98   200  78   80   35   NA    55
[2,]   32   67   15   73   NA   12   91   230  3     99
[3,]   NA   NA   NA   45   53   26   112  64   80    41
[4,]   54   38   60   70   163  69   109  205  5     31
[5,]   107  28   296  254  30   40   NA   18   28    90

Результирующие верхние 40% матрицы чисел столбцов должны выглядеть следующим образом (количество выбранных элементов рассчитывается округлением вниз, как и функция as.integer)

largest=                              smallest=
      [,1] [,2] [,3] [,4]                   [,1] [,2] [,3] [,4]  
[1,]    5   3    4    NA              [1,]    1   8    10   NA
[2,]    8   10   7    NA              [2,]    9   6    3    NA
[3,]    7   9    NA   NA              [3,]    6   10   NA   NA
[4,]    8   5    7    4               [4,]    9   10   2    1
[5,]    3   4    1    10              [5,]    8   9    2    5

Таким образом, верхние числа выбираются, глядя только на не-NA-элементы строк. Например, первая строка матрицы данных содержит только 8 не-чисел NA и, таким образом, выбирается 40% * 8 = 3,2 ~ 3 элемента. Это создает NA для результирующих матриц.

Еще раз, я попытался использовать цикл for (этот код для нахождения наибольшего 40%):

   largest <- matrix(rep(NA, 20), nrow = 5)
 for(i in 1:5){
   largest[i,]<-order(data[i,], decreasing=T)   
 [1:as.integer(0.4*nrow(data[complete.cases(data[,i]),]))]
 }

но R возвращает ошибку: «количество заменяемых элементов не кратно длине замены», что, я думаю, означает, что, поскольку не все элементы исходной самой большой матрицы не заменяются во время цикла, этот цикл for не может быть использован. Я прав?

Как можно было сделать такой выбор?

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Размещение моего (менее точного и очень похожего) ответа в виде функции, которая может быть полезна:

toppct <- function(x, p, largest = TRUE){
  t(apply(x, 1, function(y){
    c(which(y %in% sort(y, decreasing = largest)[1:floor(length(which(!is.na(y)))*p)]), 
      rep(NA, floor(length(y)*p) - floor(length(which(!is.na(y)))*p)))
  }))
}

Это приводит к выводу в вопросе, без сортировки верхних позиций процента. Для smallest, просто установите largest = FALSE.

> toppct(mat, .4)
     [,1] [,2] [,3] [,4]
[1,]    3    4    5   NA
[2,]    7    8   10   NA
[3,]    7    9   NA   NA
[4,]    4    5    7    8
[5,]    1    3    4   NA

> toppct(mat, .4, largest = FALSE)
     [,1] [,2] [,3] [,4]
[1,]    1    8   10   NA
[2,]    3    6    9   NA
[3,]    6   10   NA   NA
[4,]    1    2    9   10
[5,]    2    8    9   NA

Я хочу подчеркнуть, что я думаю, что ответ Мориса - тот, который нужно принять, поскольку он получает результат точно так, как ожидалось.

0 голосов
/ 05 июля 2018

Следующее воспроизводит ваш ожидаемый результат

# Determine number of columns for output matrix as
# maximum of 40% of all non-NA values per row
ncol <- max(floor(apply(mat, 1, function(x) sum(!is.na(x))) * 0.4))

# Top 40% largest
t(apply(mat, 1, function(x) {
    n <- floor(sum(!is.na(x)) * 0.4);
    replace(rep(NA, ncol), 1:n, order(x, decreasing = T)[1:n])
}))
#     [,1] [,2] [,3] [,4]
#[1,]    5    3    4   NA
#[2,]    8   10    7   NA
#[3,]    7    9   NA   NA
#[4,]    8    5    7    4
#[5,]    3    4    1   NA


# Top 40% smallest
t(apply(mat, 1, function(x) {
    n <- floor(sum(!is.na(x)) * 0.4);
    replace(rep(NA, ncol), 1:n, order(x, decreasing = F)[1:n])
}))
#     [,1] [,2] [,3] [,4]
#[1,]    1    8   10   NA
#[2,]    9    6    3   NA
#[3,]    6   10   NA   NA
#[4,]    9   10    2    1
#[5,]    8    2    9   NA

Объяснение: Сначала мы определяем максимальное количество столбцов для обеих выходных матриц; Затем мы перебираем mat строка за строкой, определяем специфическое для строки число n не-NA записей, соответствующих 40% всех не-NA чисел в этой строке, и возвращаем столбец vector из верхних 40% уменьшающихся / увеличивающихся записей, дополненных NA с. Окончательная транспонирование дает ожидаемый результат.

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