32

I'm try to calculate minimum across multiple columns (row-wise min) in a data frame, but the min function automatically returns the minimum across the whole of each column rather than for each row separately. I'm sure I'm missing something really simple here? Any ideas much appreciated.

x <- c(1,2,7)
y <- c(1,5,4)
minIwant <- c(1,2,4)
df <- data.frame(x, y, minIwant)
df$minIget <- min(df$x,df$y)
df
  x y minIwant minIget
1 1 1        1       1
2 2 5        2       1
3 7 4        4       1
Henrik
  • 65,555
  • 14
  • 143
  • 159
Rob
  • 599
  • 2
  • 6
  • 9
  • @RichScriven's is less intuitive (to me) but much faster, for anyone who's in optimization mode. – Jason Sep 20 '18 at 14:03

4 Answers4

49

You can use apply to go through each row

apply(df, 1, FUN = min)

Where 1 means to apply FUN to each row of df, 2 would mean to apply FUN to columns.

To remove missing values, use:

apply(df, 1, FUN = min, na.rm = TRUE)
Henrik
  • 65,555
  • 14
  • 143
  • 159
nico
  • 50,859
  • 17
  • 87
  • 112
18

We could use pmin, which finds the parallel minima of sets of values. Since our df is technically a list, we will need to run it via do.call.

df$min <- do.call(pmin, df)

which gives

df
#   x y min
# 1 1 1   1
# 2 2 5   2
# 3 7 4   4

Data:

df <- data.frame(x = c(1, 2, 7), y = c(1, 5, 4))

Furthermore, if na.rm = TRUE is needed, you can do

df$min <- do.call(pmin, c(df, na.rm = TRUE))
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
  • This is good, but does not work with NAs. How can I get this working with na.rm = TRUE? – JASC May 19 '19 at 23:20
  • 1
    @JASC - You can do `do.call(pmin, c(df, na.rm = TRUE))`. See `help(do.call)` for info on how to use a list in the `args` argument. – Rich Scriven May 21 '19 at 23:33
5

Just want to add on how you can also do this with dplyr.

library(dplyr)

x<-c(1,2,7)
y<-c(1,5,4)
df <- data.frame(x,y)

df %>% rowwise() %>% mutate(minIget = min(x, y))
# A tibble: 3 x 3
    x     y   minIget
  <dbl> <dbl>   <dbl>
1    1.    1.      1.
2    2.    5.      2.
3    7.    4.      4.
  • 3
    `df %>% mutate(minIget = pmin(x, y))` is probably more performant. – Axeman May 21 '19 at 23:49
  • 3
    The difference between dplyr's `rowwise()` and `pmin()` was significant in my application: `rowwise()` ran 21.5 seconds and `pmin()` ran 0.5 seconds. – MatSchu Nov 05 '20 at 13:19
4

We could also use rowMins from library(matrixStats)

library(matrixStats)
df$minIwant <- rowMins(as.matrix(df))
akrun
  • 874,273
  • 37
  • 540
  • 662