Daniel James
Daniel James

Reputation: 1433

R: Sort the Minimums of My Data Frame in This Order

I have the following data frame as follows:

library(future.apply)
lb <- 2:9
NBB_AR0.8 <- c(1.879, 1.065, 1.385, 1.568, 1.493, 1.732, 1.263, 0.9369)
NBB_AR0.9 <- c(0.8051, 0.7598, 1.113, 1.056, 0.9819, 0.8842, 0.679, 0.4441)
NBB_AR0.95 <- c(0.7456, 1.249, 0.8531, 1.573, 1.425, 1.181, 0.8645, 0.5171)
MBB1_AR0.8 <- c(1.806, 1.611, 1.199, 1.46, 1.253, 1.483, 1.418,1.615)
MBB1_AR0.9 <- c(0.7936, 0.7351, 0.9151, 0.9417, 0.9827, 0.9767, 0.8699, 0.9629)
MBB1_AR0.95 <- c(1.646, 1.621, 0.9941, 0.9044, 1.054, 1.247, 1.376, 1.281)
MBB2_AR0.8 <- c(1.806, 1.611, 1.199, 1.46, 1.619, 1.483, 1.498, 1.301)
MBB2_AR0.9 <- c(0.7936, 0.7351, 0.9151, 0.9417, 0.9653, 0.9767, 1.051, 0.9979)
MBB2_AR0.95 <- c(1.646, 1.621, 0.9941, 0.9044, 1.531, 1.247, 1.03, 0.9696)
MBB3_AR0.8 <- c(1.806, 1.611, 1.199, 1.46, 1.363, 1.483, 1.742, 1.161)
MBB3_AR0.9 <- c(0.7936, 0.7351, 0.9151, 0.9417, 1.025, 0.9767, 0.9018, 0.6612)
MBB3_AR0.95 <- c(1.646, 1.621, 0.9941, 0.9044, 0.861, 1.247, 1.184, 0.8825)
CBB_AR0.8 <- c(1.642, 0.9616, 1.42, 1.728, 1.326, 1.324, 1.542, 1.172)
CBB_AR0.9 <- c(0.2077, 0.2158, 0.1791, 0.1933, 0.168, 0.2211, 0.1516, 0.2133)
CBB_AR0.95 <- c(0.1039, 0.08983, 0.09176, 0.1, 0.09203, 0.08383, 0.08386, 0.08956) 
df <- data.frame(lb, NBB_AR0.8, NBB_AR0.9, NBB_AR0.95, NBB_AR0.95, MBB1_AR0.8, MBB1_AR0.9, MBB1_AR0.95, MBB2_AR0.8, MBB2_AR0.9, MBB2_AR0.95, MBB3_AR0.8, MBB3_AR0.9, MBB3_AR0.95, CBB_AR0.8, CBB_AR0.9, CBB_AR0.95)

All the three(3) above have NBB in common thus, they should be arranged in the row of NBB

All the five(5) above have AR0.8 in common thus, they should be arranged in the row of AR0.8 The others follow the same arrangement.

I wish to have the minimum values arranged as follows using R:

AR0.8 AR0.9 AR0.95
NBB 0.9369 0.4441 0.5171
MBB1 1.199 0.7351 0.9044
MBB2 1.199 0.7351 0.9044
MBB3 1.161 0.6612 0.861
CBB 0.9616 0.1516 0.08336

I tried this but got this result that does not suit my expectation in arrangement:

    future.apply::future_apply(df[-1], 2, min)

> NBB_AR0.8    NBB_AR0.9   NBB_AR0.95 NBB_AR0.95.1   MBB1_AR0.8   MBB1_AR0.9  MBB1_AR0.95   MBB2_AR0.8   MBB2_AR0.9  MBB2_AR0.95   MBB3_AR0.8 
     0.93690      0.44410      0.51710      0.51710      1.19900      0.73510      0.90440      1.19900      0.73510      0.90440      1.16100 
  MBB3_AR0.9  MBB3_AR0.95    CBB_AR0.8    CBB_AR0.9   CBB_AR0.95 
     0.66120      0.86100      0.96160      0.15160      0.08383 


The answers is correct but I am also interested in the arrangement.

I am also interested in this method:

future.apply::future_apply(df[-1], 2, which.min)

which gives me this:

NBB_N10_AR0.8_RMSE NBB_N10_AR0.9_RMSE NBB_N10_AR0.95_RMSE NBB_N10_AR0.95_RMSE.1 MBB1_N10_AR0.8_RMSE MBB1_N10_AR0.9_RMSE 8 8 8 8 3 2 MBB1_N10_AR0.95_RMSE MBB2_N10_AR0.8_RMSE MBB2_N10_AR0.9_RMSE MBB2_N10_AR0.95_RMSE MBB3_N10_AR0.8_RMSE MBB3_N10_AR0.9_RMSE 4 3 2 4 8 8 MBB3_N10_AR0.95_RMSE CBB_N10_AR0.8_RMSE CBB_N10_AR0.9_RMSE CBB_N10_AR0.95_RMSE 5 2 7 6

I want it to be arranged as this table:

AR0.8 AR0.9 AR0.95
NBB 9 9 9
MBB1 4 3 5
MBB2 4 3 5
MBB3 9 9 6
CBB 3 8 8

All the three(3) above have NBB in common thus, they should be arranged in the row of NBB

All the five(5) above have AR0.8 in common thus, they should be arranged in the row of AR0.8

Upvotes: 1

Views: 344

Answers (2)

akrun
akrun

Reputation: 887048

We may use

lst1 <- split(setNames(out, sub(".*_", "", names(out))),  sub("_.*", "", names(out)))
do.call(rbind, lapply(lst1, function(x) x[!duplicated(x)]))

-ouptut

    AR0.8  AR0.9  AR0.95
CBB  0.9616 0.1516 0.08383
MBB1 1.1990 0.7351 0.90440
MBB2 1.1990 0.7351 0.90440
MBB3 1.1610 0.6612 0.86100
NBB  0.9369 0.4441 0.51710

lst2 <- split(setNames(out2, sub(".*_", "", names(out2))),  sub("_.*", "", names(out2)))
 do.call(rbind, lapply(lst2, `[`, 1:3))
     AR0.8 AR0.9 AR0.95
CBB      2     7      6
MBB1     3     2      4
MBB2     3     2      4
MBB3     8     8      5
NBB      8     8      8

data

out <- future.apply::future_apply(df[-1], 2, min)
out2 <- future.apply::future_apply(df[-1], 2, which.min)

Upvotes: 2

Martin Gal
Martin Gal

Reputation: 16978

A tidyverse solution could be

library(tidyr)
library(dplyr)

df %>% 
  pivot_longer(-c(lb), names_to = c("name", "name2"), names_pattern = "(.*)_(.*)") %>% 
  select(-lb) %>% 
  group_by(name, name2) %>% 
  slice_min(value) %>% 
  pivot_wider(names_from = name2) %>% 
  ungroup()

returning

# A tibble: 5 x 4
  name  AR0.8 AR0.9 AR0.95
  <chr> <dbl> <dbl>  <dbl>
1 CBB   0.962 0.152 0.0838
2 MBB1  1.20  0.735 0.904 
3 MBB2  1.20  0.735 0.904 
4 MBB3  1.16  0.661 0.861 
5 NBB   0.937 0.444 0.517 

Upvotes: 2

Related Questions