2015-04-28 2 views
2

Я хотел бы получить индекс минимума некоторого подмножества вектора, но индекс в исходном векторе, а не перенумерованное подмножество.which.min на подмножество вектора

На данный момент, я использую:

L = rnorm(20) # say this is the original vector 
subset = runif(20)<0.3 # some conditions to extract the subset 
ind_min = which.min(L[subset]) 
ind_sel = seq(L)[subset] 
ind_min = ind_sel[ind_min] 

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

L_tmp = L 
L_tmp[!subset] = Inf 
ind_min = which.min(L_tmp) 

, который apparentlty более эффективным:

> microbenchmark(method_1(), method_2(), unit = "relative") 
Unit: relative 
     expr  min  lq  mean median  uq  max neval 
method_1() 3.699562 3.249635 3.119666 3.076819 2.928259 3.225849 100 
method_2() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100 

, но я не очень доволен, потому что я думаю, там должно быть что-то еще. Любое предложение ?

ответ

2

Вы можете найти мин. В L[subset]. А затем получите индекс в L.

L = rnorm(20) # say this is the original vector 
subset = runif(20)<0.3 # some conditions to extract the subset 
min = min(L[subset]) 
ind_min = intersect(which(L == min), seq(L)[subset])[1] 
+1

Имейте в виду, что 'which.min' находит первое минимальное значение, тогда как' which' находит все значения, удовлетворяющие условию. – Roland

+0

Роланд, ты прав, спасибо! –

+1

По-видимому, такая же быстрая, как и моя вторая опция, но все вписываются в одну строку: 'ind_min = intersect (что (L == min (L [подмножество])), seq (L) [subset])', так что это может быть лучше! Btw есть ошибка, вы должны добавить 'seq (L) [подмножество]' – clemlaflemme

4

вы можете попробовать:

(seq(L))[subset][which.min(L[subset])] 

, который похож на ваш первый метод, но без создания временных переменных

результата бенчмарка на 20000 длинном векторе L:

method_cath<- function(){(seq(L))[subset][which.min(L[subset])]} 
    method_FK_corr1 <- function(){min = min(L[subset]) 
            ind_min = intersect(which(L == min), seq(L)[subset])[1] 
            return(ind_min)} 
    method_FK_corr2 <- function(){min = min(L[subset]) 
            ind_min = intersect(which(L == min), which(subset))[1] 
            return(ind_min)} 
    method_1clm <- function(){ind_min = which.min(L[subset]) 
           ind_sel = seq(L)[subset] 
           ind_min = ind_sel[ind_min] 
           return(ind_min)} 
    method_2clm <- function(){L_tmp = L 
           L_tmp[!subset] = Inf 
           ind_min = which.min(L_tmp) 
           return(ind_min)} 

> microbenchmark(method_2clm(), method_cath(), method_1clm(), method_FK_corr2(), method_FK_corr1(), unit = "relative") 
    # Unit: relative 
    #    expr  min  lq  mean median  uq  max neval cld 
    #  method_2clm() 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 100 a 
    #  method_cath() 1.312146 1.290370 1.282964 1.278178 1.282424 0.9191693 100 b 
    #  method_1clm() 1.295031 1.294642 1.303781 1.284630 1.279821 1.2977193 100 b 
    # method_FK_corr2() 1.185821 1.166924 1.278030 1.155217 1.165738 4.9948007 100 b 
    # method_FK_corr1() 1.683783 1.644797 1.746055 1.635293 1.636195 5.1616672 100 c 

NB: В результате я получил NA с @FedorenkoKristina оригинальная функция, я протестировал две возможные исправленные функции, теперь все функции дают одинаковый результат.

0

Возможно, вы также можете использовать подмножество. Где подмножество - это ваше состояние.

L = rnorm(20) # say this is the original vector 
subset = runif(20)<0.3 # some conditions to extract the subset 
ind_min = which(L == min(subset(L,subset))) 

Я думаю, это очень похоже на то, что предложил Федоренко Кристина. Она была быстрее меня.

Смежные вопросы