Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find the min in the vector but no 0

Tags:

r

dplyr

My df is like this

  df <- data.frame(t1 = c(10, 20, 30, 1, 0), t2 = c(30, 0, 40, 0, 0), t3 = c(10, 0, 3, 10, 0))

what I want to do is to find the min in the df row but not 0 I do

df<- df%>% rowwise() %>%
  do({
    th <- c(.$t1, .$t2, .$t3,)


    data.frame(., t_s_last = min(th[th > 0))
  })

but it works but not for the rows that contain sth more than 0. how to make this returning 0 if there are just 0 in the row (row 5)?

like image 301
Mateusz1981 Avatar asked Aug 31 '15 10:08

Mateusz1981


2 Answers

We can use apply with an if/else condition

 apply(df, 1, function(x) if(all(x==0)) 0 else min(x[x> 0]))

Or another option is rowMins from library(matrixStats). We replace the '0' values in the dataset with NA, use rowMins with na.rm=TRUE, and replace the 'Inf' values with 0.

 library(matrixStats)
 is.na(df) <- df==0
 v1 <- rowMins(as.matrix(df), na.rm=TRUE)
 v1[is.infinite(v1)] <- 0
 v1
 #[1] 10 20  3  1  0

We can also use the if/else within the do

library(dplyr)
df %>%
    rowwise() %>%
    do({th <- unlist(.[.>0])
       data.frame(., t_s_last = if(all(th==0)) 0 else min(th))})
#  t1 t2 t3 t_s_last
#1 10 30 10       10
#2 20  0  0       20
#3 30 40  3        3
#4  1  0 10        1
#5  0  0  0        0
like image 113
akrun Avatar answered Oct 09 '22 19:10

akrun


I'm guessing that because you are looking for values above zero, all your values are >=0 and integers. Thus, we could play around with log transformation in order to convert all the zeroes to Inf and thus being always the largest. This will help us avoid running by row operations, rather vectorize using the minus of the max.col function

df[cbind(1:nrow(df), max.col(-abs(log(df))))]
## [1] 10 20  3  1  0
like image 25
David Arenburg Avatar answered Oct 09 '22 19:10

David Arenburg