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