Arrange some observations in dataframe by one column, and others by another

Viewed 70

I have the following dataframe:

dat<- data.frame(question=c("Question 1", "Question 3", "Question 2", 
                      "Question 2", "Question 3", "Question 1"),
           answer=c("Answer 1", "Answer 1", "1- Yes", "No",
                    "Answer 2", "Answer 2"),
           total=c(40,70,20,80,30,60))
dat

#    question   answer total
# 1 Question 1 Answer 1    40
# 2 Question 3 Answer 1    70
# 3 Question 2   1- Yes    20
# 4 Question 2       No    80
# 5 Question 3 Answer 2    30
# 6 Question 1 Answer 2    60

I want to arrage the dataframe according to the order of the variable question , and by either the variable answer or total, depending on the value of question. If question == "Question 1" or question == "Question 3", I would like to arrange by total, and if question == "Question 2" I would like to arrange by answer. This is the output I want to achieve:

#     question   answer total
# 1 Question 1 Answer 2    60
# 2 Question 1 Answer 1    40
# 3 Question 2   1- Yes    20
# 4 Question 2       No    80
# 5 Question 3 Answer 1    70
# 6 Question 3 Answer 2    30

How can I achieve this? Ideally, I would like a solution using Dplyr's arrange(). I have tried by combining arrange() and ifelse() but have not gotten the results I want. This is what I have tried:

library(tidyverse)
dat %>% arrange(question, ifelse(question=="Question 2", answer, desc(total)))
2 Answers

You can use the .by_group argument of arrange()

    dat %>% 
        group_by(question) %>% 
        arrange(.by_group = T, desc(ifelse(question == "Question 2", answer, total)) )
        %>% ungroup()

arrange with case_when ought to do the job:


dat %>% arrange(
            question,
            case_when(
                question %in% c("Qustion 1","Question 3") ~ as.double(desc(total)),
                question == "Question 2" ~ as.double(xtfrm(answer))
            )
        )

Now I've somewhat baffled by why as.double is needed there, but it complains otherwise, and seems to do the right thing with it there.

Btw, you'r approach works with as.double too:


dat %>% arrange(question, if_else(question=="Question 2", as.double(xtfrm(answer)), as.double(desc(total))))

(but will be limited to handle two columns unless you nest multiple if_else's (dplyr::if_else is preferable to base::ifelse ))

Related