Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate row-wise maximum

Tags:

r

data.table

I would like to create a new column, which equals to the maximum value of all columns of that row.

Here is an example:

library(data.table)
data <- data.table(head(iris))
data[ , Species := NULL]
data

   Sepal.Length Sepal.Width Petal.Length Petal.Width
1:          5.1         3.5          1.4         0.2
2:          4.9         3.0          1.4         0.2
3:          4.7         3.2          1.3         0.2
4:          4.6         3.1          1.5         0.2
5:          5.0         3.6          1.4         0.2
6:          5.4         3.9          1.7         0.4

I can't really use the max function here, because it is going to find the maximum value of all columns, e.g., data[, max_value := max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width)]. What I want is something like this:

   Sepal.Length Sepal.Width Petal.Length Petal.Width max_value
1:          5.1         3.5          1.4         0.2       5.1
2:          4.9         3.0          1.4         0.2       4.9
3:          4.7         3.2          1.3         0.2       4.7
4:          4.6         3.1          1.5         0.2       4.6
5:          5.0         3.6          1.4         0.2       5.0
6:          5.4         3.9          1.7         0.4       5.4
like image 314
Boxuan Avatar asked Mar 06 '15 23:03

Boxuan


1 Answers

Using dplyr you could do:

library(dplyr)
setDF(data) %>% 
  rowwise() %>% 
  mutate(max = max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width))

#Source: local data frame [10 x 5]
#Groups: <by row>
#
#   Sepal.Length Sepal.Width Petal.Length Petal.Width max
#1           5.1         3.5          1.4         0.2 5.1
#2           4.9         3.0          1.4         0.2 4.9
#3           4.7         3.2          1.3         0.2 4.7
#4           4.6         3.1          1.5         0.2 4.6
#5           5.0         3.6          1.4         0.2 5.0
#6           5.4         3.9          1.7         0.4 5.4

Or as @akrun suggested:

setDF(data) %>% mutate(max=pmax(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width))

Which is much faster than the rowwise() approach:

n <- 10e6; nc <- 4; DT <- data.table(replicate(nc,rnorm(n))) 

mbm <- microbenchmark(
  steven = DT %>% rowwise() %>% mutate(V5 = max(V1, V2, V3, V4)),
  frank = DT[,c(.SD,list(do.call(pmax,.SD)))], 
  akrun = DT %>% mutate(V5 = pmax(V1, V2, V3, V4)), times = 25, unit = "relative")

enter image description here

#Unit: relative
#   expr      min        lq      mean   median        uq       max neval cld
# steven 17.93647 18.024734 17.535764 17.42948 17.484920 16.446384    25   b
#  frank  1.00000  1.000000  1.000000  1.00000  1.000000  1.000000    25  a 
#  akrun  1.00220  1.002281  1.013604  1.00240  1.003089  1.001262    25  a 
like image 62
Steven Beaupré Avatar answered Oct 28 '22 17:10

Steven Beaupré