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)?
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With