Справка R: ведите n записей в каждом столбце

Снова я застрял на матричных манипуляциях, которые, вероятно, могли бы быть решены с помощью apply или loop
У меня есть большой фрейм данных, из которого я хотел бы сохранить определенное число n из самых высоких значений в столбце. Но размеры фрейма данных не должны быть изменены. Поэтому я подумал, что это хорошая идея сделать это так:
1. Найдите n-е наибольшее число в столбце с помощью (в данном случае: третье по величине, вычисленное с помощью других сообщений)

x <- c(0.2, 0.23, 0.35, 0.56, 0.12, 0.7, 0, 0.66, 0.45, 0.21, 0.49, 0.47, 0.1, 0.63, 0.55)
m <- matrix(data = x, nrow=4, ncol = 4)
>m
     [,1] [,2] [,3] [,4]
[1,] 0.20 0.12 0.45 0.47
[2,] 0.23 0.70 0.21 0.10
[3,] 0.35 0.00 0.49 0.63
[4,] 0.56 0.66 0.43 0.55

m.low <- apply(m, 2, function(i) sort(i)[ dim(m)[1]-2])

2. замените все значения ниже значения в m.low на 0, сделанное для каждого столбца. Это где я не знаю, как дальше... Желаемый результат должен выглядеть примерно так:

 > m.new
     [,1] [,2] [,3] [,4]
[1,] 0.00 0.12 0.45 0.47
[2,] 0.23 0.70 0.00 0.00
[3,] 0.35 0.00 0.49 0.63
[4,] 0.56 0.66 0.43 0.55

Буду очень признателен, если кто-нибудь сможет мне помочь и добавить какое-нибудь объяснение функции в пост. Кроме того, может быть более простой способ без предварительного поиска n-го значения. Спасибо!

* Отредактировал m для лучшей воспроизводимости и добавил m.new по желанию. Сожалею!

3 ответа

Решение

Вы можете попробовать использовать apply с "MARGIN=2", чтобы перебрать столбцы m, Приведенный ниже код аналогичен тому, который вы использовали для m.low, за исключением того, что он использует replace функция для замены элементов в каждом столбце на основе аргумента условия i < sort(i).. до 0.

apply(m, 2, function(i) replace(i, i<sort(i)[ dim(m)[1]-2],0))
#      [,1] [,2] [,3] [,4]
#[1,] 0.00 0.12 0.45 0.47
#[2,] 0.23 0.70 0.00 0.00
#[3,] 0.35 0.00 0.49 0.63
#[4,] 0.56 0.66 0.43 0.55

Или из m.low

m[m <m.low[col(m)]] <- 0

Или создайте "indx", используя ave

indx <- !!ave(m, col(m), FUN=function(i) i <sort(i)[dim(m)[1]-2])
m[indx] <- 0

Или вы можете конвертировать m "data.frame" и использовать mutate_each/replace комбо

library(dplyr)
as.data.frame(m) %>% 
            mutate_each(funs(replace(., .<sort(.)[2], 0)))
f <- function(vec){
  bound = sort(vec)[length(vec)-2]
  vec[which(vec<bound)] = 0
  vec
}
res <- apply(m,2,f)

Вы могли бы попробовать mapply, Чтобы он работал, он должен распознавать каждый столбец как свой собственный элемент, поэтому я использую несколько заурядный as.list(as.data.frame()):

mapply( m.low, as.list(as.data.frame(m)), FUN = function(low,col) {
  col[ col < low ] <- 0
  col
} )
Другие вопросы по тегам