alexvpickering
alexvpickering

Reputation: 642

order by absolute values of one column while keeping equal values of another column together in R

Example data.frame:

df <- data.frame(study = c('A', 'A', 'B', 'C', 'D', 'D'),
                 similarity = c(0.61, 0.58, -0.605, 0.4, 0.607, 0.3))

df
   study similarity
1     A      0.610
2     A      0.580
3     B     -0.605
4     C      0.400
5     D      0.607
6     D      0.300

I want to order by absolute similarity, but keeping equal values of study together. For the above example the result should be:

   study similarity
1     A      0.610
2     A      0.580
5     D      0.607
6     D      0.300
3     B     -0.605
4     C      0.400

Upvotes: 1

Views: 752

Answers (4)

acylam
acylam

Reputation: 18681

data.table solution:

library(data.table)
setDT(df)[order(-abs(similarity)), .SD, by = study]

Result:

   study similarity
1:     A      0.610
2:     A      0.580
3:     D      0.607
4:     D      0.300
5:     B     -0.605
6:     C      0.400

Upvotes: 3

www
www

Reputation: 39154

A solution using dplyr. This solution looks more complicated than others, but it aims to generate the expected output even if the study column is not in order, or there are ties in similarity from different study group.

First, Calculate the absolute value of each similarity (df2).

Second, Calcualte the maximum absolute of each study (df3).

Third, Covert the study column to a factor column based on the order in df3. Arrange the columns based on study and absolute value (df4)

library(dplyr)

df2 <- df %>% mutate(ABS = abs(similarity))

df3 <- df2 %>%
  group_by(study) %>%
  summarise(Max_ABS = max(ABS)) %>%
  arrange(desc(Max_ABS))

df4 <- df2 %>%
  mutate(study = factor(study, levels = df3$study)) %>%
  arrange(study, desc(ABS)) %>%
  select(-ABS)
df4
#   study similarity
# 1     A      0.610
# 2     A      0.580
# 3     D      0.607
# 4     D      0.300
# 5     B     -0.605
# 6     C      0.400

Upvotes: 0

BENY
BENY

Reputation: 323276

In base R

df[order(-ave(df$similarity,df$study,FUN=function(x) max(abs(x))),df$study),]
  study similarity
1     A      0.610
2     A      0.580
5     D      0.607
6     D      0.300
3     B     -0.605
4     C      0.400

Upvotes: 2

missuse
missuse

Reputation: 19716

Here is an approach using tidyverse

library(tidyverse)

 df %>%
    group_by(study) %>%  #group by study
    mutate(arr = max(abs(similarity))) %>% #get maximum absolute similarity by group
    ungroup() %>%
    arrange(desc(arr)) %>% #arrange according to by group maximum absolute similarity
    select(-arr) #leave the helper column out
#ouput

# A tibble: 6 x 2
   study similarity
  <fctr>      <dbl>
1      A      0.610
2      A      0.580
3      D      0.607
4      D      0.300
5      B     -0.605
6      C      0.400

Upvotes: 1

Related Questions