Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add Min Row in R

Tags:

r

min

I have read a lot of similar questions, but cannot get any of the code to work. I simply want to add a row to the bottom of my data frame (df) that has the min value for each column for columns 2:8. Below is my code (that works) to add a total line, but I want a min line.

df[(nrow(df)+ 1),(2:8)] <- colSums(df[,2:8], na.rm=TRUE)

I have tried to get colMins in package matrixStats to work, but can't for some reason. Any help would be appreciated!

like image 227
stevenjoe Avatar asked Dec 02 '15 06:12

stevenjoe


Video Answer


2 Answers

In base R, you can use sapply() to create an atomic vector of column minimums and then rbind() to attach it to the original data. I added an NA for the first value, since we need something there to add it to the original data.

rbind(df, c(NA, sapply(df[2:8], min, na.rm = TRUE)))

Obviously this assumes only 8 columns, and so df[-1] can be used in place of df[2:8].

And for a speed increase we can use vapply() over sapply() because we know the result will be a single numeric value.

rbind(df, c(NA, vapply(df[-1], min, 1, na.rm = TRUE)))

Update: In response to your comment on the other answer - to get "MIN" in the first column and the minimum values in all the rest, we can adjust the call to a named list and do it all in one go. This way we don't mix the column classes (character and numeric) and end up with unexpected classes in the columns of the resulting data.

rbind(
    df, 
    c(setNames(list("MIN"), names(df)[1]), lapply(df[-1], min, na.rm = TRUE))
)
like image 128
Rich Scriven Avatar answered Sep 28 '22 08:09

Rich Scriven


We can try colMins from library(matrixStats)

library(matrixStats)
rbind(df, c(NA,colMins(as.matrix(df[2:8]))))

Update

To replace NA with 'MIN',

rbind(df, c('MIN',as.list(colMins(as.matrix(df[2:8])))))

Or another approach would be to convert to matrix and use addmargins

addmargins(`row.names<-`(as.matrix(df[-1]), df$ID), 1, FUN=min)

data

set.seed(24)
df <- cbind(ID= 1:10,as.data.frame(matrix(sample(1:9, 7*10, 
   replace=TRUE), ncol=7)))
like image 29
akrun Avatar answered Sep 28 '22 10:09

akrun