Adam Amin
Adam Amin

Reputation: 1476

How to find the minimum and maximum in many rows per single value

I have the following dataset:

Class     
A       5     9     2     6
A       13    8     
A       4     8     3     10    6
B       12    5     11     
B       7     1     17    6     8     1

What I want is to find the maximum and minimum value for each class in all the rows that are related to that class. In this case, I should get:

Class    Max    Min
A        13     2
B        33     1

Note that the values don't have headers.

How can I do that?

Upvotes: 1

Views: 78

Answers (2)

tmfmnk
tmfmnk

Reputation: 40171

Using the data provided by @G. Grothendieck, a tidyverse possibility:

DF %>%
 gather(var, val, -Class) %>%
 group_by(Class) %>%
 summarise(Max = max(val, na.rm = TRUE),
        Min = min(val, na.rm = TRUE))

   Class   Max   Min
  <chr> <dbl> <dbl>
1 A       13.    2.
2 B       17.    1.

It is transforming the data from wide to long and the identifies the minimum and maximum value per "Class".

Or:

cols <- names(DF)[2:length(DF)]

DF %>% 
 group_by(Class) %>%
 summarise(Max = max(pmax(c(!!! rlang::syms(cols)), na.rm = TRUE), na.rm = TRUE),
        Min = min(pmin(c(!!! rlang::syms(cols)), na.rm = TRUE), na.rm = TRUE))

First, it identifies the columns which you want to summarise. Then, it summarises the maximum and minimum of row-wise maximum and minimum.

Or:

cols <- names(DF)[2:length(DF)]

DF %>% 
 rowwise() %>%
 mutate(Max = max(c(!!! rlang::syms(cols)), na.rm = TRUE),
        Min = min(c(!!! rlang::syms(cols)), na.rm = TRUE)) %>%
 group_by(Class) %>%
 summarise(Max = max(Max, na.rm = TRUE),
           Min = min(Min, na.rm = TRUE))

First, it identifies the columns which you want to summarise. Second, it calculates the row-wise maximum and minimum of the selected columns. Third, it groups by "Class" and summarises the maximum and minimum of row-wise maximum and minimum.

Upvotes: 1

G. Grothendieck
G. Grothendieck

Reputation: 270348

Assuming the input DF shown reproducibly in the Note at the end:

min.max <- do.call("rbind", by(DF[-1], DF[[1]], range, na.rm = TRUE))
colnames(min.max) <- c("min", "max")
min.max

giving this matrix:

  min max
A   2  13
B   1  17

Note

Lines <- "
A       5     9     2     6
A       13    8     
A       4     8     3     10    6
B       12    5     11     
B       7     1     17    6     8     1"
DF <- read.table(text = Lines, as.is = TRUE, fill = TRUE)
names(DF)[1] <- "Class"

Upvotes: 2

Related Questions