2

I have this data.set

  people <- c("Arthur", "Jean", "Paul", "Fred", "Gary")
  question1 <- c(1, 3, 2, 2, 5)
  question2 <- c(1, 0, 1, 0, 3)
  question3<- c(1, 0, 2, 2, 4)
  question4 <- c(1, 5, 2, 1, 5)

  test <- data.frame(people, question1, question2, question3, question4)

  test

Here is my output :

     people question1 question2 question3 question4
   1 Arthur         1         1         1         1
   2   Jean         3         0         0         5
   3   Paul         2         1         2         2
   4   Fred         2         0         2         1
   5   Gary         5         3         4         5

I want to order the results of each people like this (descending order based on values from left to right columns) in a new data.frame. Ne names of the new columns are letters or anything else.

     people          A        B         C         D
   1 Arthur         1         1         1         1
   2   Jean         5         3         0         0
   3   Paul         2         2         2         1
   4   Fred         2         2         2         0
   5   Gary         5         5         4         3
Wilcar
  • 1,831
  • 1
  • 14
  • 39

4 Answers4

2

With base R apply function sort to the rows in question but be carefull, apply returns the transpose:

test[-1] <- t(apply(test[-1], 1, sort, decreasing = TRUE))

test
#  people question1 question2 question3 question4
#1 Arthur         1         1         1         1
#2   Jean         5         3         0         0
#3   Paul         2         2         2         1
#4   Fred         2         2         1         0
#5   Gary         5         5         4         3
Rui Barradas
  • 44,483
  • 8
  • 22
  • 48
1

One dplyr and tidyr option could be:

test %>%
 pivot_longer(-people) %>%
 group_by(people) %>%
 arrange(desc(value), .by_group = TRUE) %>%
 mutate(name = LETTERS[1:n()]) %>%
 pivot_wider(names_from = "name", values_from = "value")

  people     A     B     C     D
  <fct>  <dbl> <dbl> <dbl> <dbl>
1 Arthur     1     1     1     1
2 Fred       2     2     1     0
3 Gary       5     5     4     3
4 Jean       5     3     0     0
5 Paul       2     2     2     1
tmfmnk
  • 31,986
  • 3
  • 26
  • 41
1

Solution using tidyverse (i.e. dplyr and tidyr):

library(tidyverse)
test %>%
  pivot_longer(cols=-people, names_to="variable",values_to = "values") %>% 
  arrange(people, -values) %>% 
  select(people, values) %>% 
  mutate(new_names = rep(letters[1:4], length(unique(test$people)))) %>% 
  pivot_wider(names_from = new_names,
              values_from = values)

This returns:

# A tibble: 5 x 5
  people     a     b     c     d
  <fct>  <dbl> <dbl> <dbl> <dbl>
1 Arthur     1     1     1     1
2 Fred       2     2     1     0
3 Gary       5     5     4     3
4 Jean       5     3     0     0
5 Paul       2     2     2     1

Explanation:

  1. bring data into 'long' form so we can order it on the values of all the 'question' variables.

  2. order (arrange) on people and -values (see above)

  3. remove the not used variable variable

  4. create a new column to hold the new names, name them A-D, for each value of person

  5. bring the data into 'wide' form, creating new columns from the new names

dario
  • 4,863
  • 1
  • 9
  • 23
0

Here's another tidyverse approach that relies on pmap() and unnest_wider().

library(tidyverse)

test %>%
  transmute(people, x = pmap(.[-1], function(...) sort(c(...), decreasing = TRUE) %>% set_names(LETTERS[seq_along(test[-1])]))) %>%
  unnest_wider(x)

# A tibble: 5 x 5
  people     A     B     C     D
  <fct>  <dbl> <dbl> <dbl> <dbl>
1 Arthur     1     1     1     1
2 Jean       5     3     0     0
3 Paul       2     2     2     1
4 Fred       2     2     1     0
5 Gary       5     5     4     3
27 ϕ 9
  • 17,064
  • 3
  • 26
  • 36