13
votes

How can I get with dplyr the minimum (or mean) value of each row on a data.frame? I mean the same result as

apply(mydataframe, 1, mean) 
apply(mydataframe, 1, min)

I've tried

mydataframe %>% rowwise() %>% mean

or

mydataframe %>% rowwise() %>% summarise(mean)

or other combinations but I always get errors, I don't know the proper way.

I know that I could also use rowMeans, but there is no simple "rowMin" equivalent. There also exist a matrixStats package but most functions don't accept data.frames, only matrixes.

If I want to calculate the min rowwise I could use
do.call(pmin, mydataframe) Is there anything simple like this for the rowwise mean?

do.call(mean, mydataframe) 

doesn't work, I guess I need a pmean function or something more complex.

Thanks

In order to compare the results we could all work on the same example:

set.seed(124)
df <- data.frame(A=rnorm(10), B=rnorm(10), C=rnorm(10))
6
Use mutate instead of summarise, by the way do.call(pmin, mydataframe) is a row wise mean- try, do.call(pmin, mtcars[c("gear", "carb")]) for example, so not sure what's your issue with itDavid Arenburg
Could you write the full sentence, please? And how do you include options for "mean", for example na.rm=TRUEskan
For example, (for the mtcars datra): mtcars %>% rowwise() %>% do(data.frame(., res = mean(unlist(.), na.rm = TRUE)))David Arenburg
The time cost of as.matrix to use matrixStats would be pretty low. Also, something like mtcars[cbind(1:nrow(mtcars),max.col(-mtcars))] works to find a minimum in each row.thelatemail
@skan a max of a negative is a minthelatemail

6 Answers

13
votes

I suppose this is what you were trying to accomplish:

df <- data.frame(A=rnorm(10), B=rnorm(10), C=rnorm(10))

library(dplyr)
df %>% rowwise() %>% mutate(Min = min(A, B, C), Mean = mean(c(A, B, C)))

#             A          B           C        Min        Mean
# 1   1.3720142  0.2156418  0.61260582  0.2156418  0.73342060
# 2  -1.4265665 -0.2090585 -0.05978302 -1.4265665 -0.56513600
# 3   0.6801410  1.5695065 -2.70446924 -2.7044692 -0.15160724
# 4   0.0335067  0.8367425 -0.83621791 -0.8362179  0.01134377
# 5  -0.2068252 -0.2305140  0.23764322 -0.2305140 -0.06656532
# 6  -0.3571095 -0.8776854 -0.80199141 -0.8776854 -0.67892877
# 7   1.0667424 -0.6376245 -0.41189564 -0.6376245  0.00574078
# 8  -1.0003376 -1.5985281  0.90406055 -1.5985281 -0.56493504
# 9  -0.8218494  1.1100531 -1.12477401 -1.1247740 -0.27885677
# 10  0.7868666  0.6099156 -0.58994138 -0.5899414  0.26894694
7
votes

There seems to be talk that some dplyr functions like rowwise could be deprecated in the long term (such rumblings on display here). Instead, certain functions from the map family of functions -- such as the pmap function -- from purrr can be used to perform this sort of calculation:

library(tidyverse)

df %>% mutate(Min = pmap(df, min), Mean = rowMeans(.))

#              A          B           C        Min       Mean
# 1  -1.38507062  0.3183367 -1.10363778  -1.385071 -0.7234572
# 2   0.03832318 -1.4237989  0.44418506  -1.423799 -0.3137635
# 3  -0.76303016 -0.4050909 -0.20495061 -0.7630302 -0.4576905
# 4   0.21230614  0.9953866  1.67563243  0.2123061  0.9611084
# 5   1.42553797  0.9588178 -0.13132225 -0.1313222  0.7510112
# 6   0.74447982  0.9180879 -0.19988298  -0.199883  0.4875616
# 7   0.70022940 -0.1509696  0.05491242 -0.1509696  0.2013907
# 8  -0.22935461 -1.2230688 -0.68216549  -1.223069 -0.7115296
# 9   0.19709386 -0.8688243 -0.72770415 -0.8688243 -0.4664782
# 10  1.20715377 -1.0424854 -0.86190429  -1.042485 -0.2324120

Mean is a special case (hence the use of the base function rowMeans), since mean on data.frame objects was deprecated with R 3.0.

5
votes

How about this?

library(dplyr)
as.data.frame(t(mtcars)) %>%
  summarise_all(funs(mean))

For extra clarity, you could add another t() at the end:

as.data.frame(t(mtcars)) %>%
  summarise_all(funs(mean)) %>%
  t()
2
votes

One dplyr and purrr option where the select helpers could be used:

df %>%
 mutate(Min = select(., everything()) %>% reduce(pmin),
        Max = select(., everything()) %>% reduce(pmax))

             A          B           C        Min        Max
1  -1.38507062  0.3183367 -1.10363778 -1.3850706  0.3183367
2   0.03832318 -1.4237989  0.44418506 -1.4237989  0.4441851
3  -0.76303016 -0.4050909 -0.20495061 -0.7630302 -0.2049506
4   0.21230614  0.9953866  1.67563243  0.2123061  1.6756324
5   1.42553797  0.9588178 -0.13132225 -0.1313222  1.4255380
6   0.74447982  0.9180879 -0.19988298 -0.1998830  0.9180879
7   0.70022940 -0.1509696  0.05491242 -0.1509696  0.7002294
8  -0.22935461 -1.2230688 -0.68216549 -1.2230688 -0.2293546
9   0.19709386 -0.8688243 -0.72770415 -0.8688243  0.1970939
10  1.20715377 -1.0424854 -0.86190429 -1.0424854  1.2071538
2
votes

With dplyr 1.0.0 you could use rowwise with c_across :

library(dplyr)

df %>%
  rowwise() %>%
  mutate(Min = min(c_across(A:C)), 
          Mean = mean(c_across(A:C)))

#       A      B       C    Min   Mean
#     <dbl>  <dbl>   <dbl>  <dbl>  <dbl>
# 1 -1.39    0.318 -1.10   -1.39  -0.723
# 2  0.0383 -1.42   0.444  -1.42  -0.314
# 3 -0.763  -0.405 -0.205  -0.763 -0.458
# 4  0.212   0.995  1.68    0.212  0.961
# 5  1.43    0.959 -0.131  -0.131  0.751
# 6  0.744   0.918 -0.200  -0.200  0.488
# 7  0.700  -0.151  0.0549 -0.151  0.201
# 8 -0.229  -1.22  -0.682  -1.22  -0.712
# 9  0.197  -0.869 -0.728  -0.869 -0.466
#10  1.21   -1.04  -0.862  -1.04  -0.232
0
votes

Think found a solution - just transpose your data.frame:

x <- data_frame(x = rnorm(10), 
            y = rnorm(10))

# A tibble: 10 × 2
        x             y
    <dbl>         <dbl>
1  -1.1240392  0.9306028477
2  -0.8213379  0.2500495105
3  -0.8289104 -0.3693704483
4  -0.6486601 -1.1421141986
5   0.5098542 -0.3703368343
6  -0.3644690 -0.0003744377
7   0.7404057  0.1166905738
8  -0.2475214 -0.0802864865
9   0.2637841 -0.7717699521
10  1.4092874  0.2998021578

x %>% 
  t() %>% 
  data.frame() %>% 
  mutate_all(funs(min)) %>% 
  unique() %>% 
  t()

         1
X1  -1.1240392
X2  -0.8213379
X3  -0.8289104
X4  -1.1421142
X5  -0.3703368
X6  -0.3644690
X7   0.1166906
X8  -0.2475214
X9  -0.7717700
X10  0.2998022