8

What is a good way to perform the following task?

I have a data frame, for example:

v2 <- c(4.5, 2.5, 3.5, 5.5, 7.5, 6.5, 2.5, 1.5, 3.5)
v1 <- c(2.2, 3.2, 1.2, 4.2, 2.2, 3.2, 2.2, 1.2, 5.2)
lvl <- c("a","a","a","b","b","b","c","c","c")
d <- data.frame(v1,v2,lvl)

> d
   v1  v2 l
1 2.2 4.5 a
2 3.2 2.5 a
3 1.2 3.5 a
4 4.2 5.5 b
5 2.2 7.5 b
6 3.2 6.5 b
7 2.2 2.5 c
8 1.2 1.5 c
9 5.2 3.5 c

Within each level of d$lvl, I want to sort the data frame by value of d$v1. So I want to get

   v1  v2 l
3 1.2 3.5 a
1 2.2 4.5 a
2 3.2 2.5 a

5 2.2 7.5 b
6 3.2 6.5 b
4 4.2 5.5 b

8 1.2 1.5 c
7 2.2 2.5 c
9 5.2 3.5 c
Ferdinand.kraft
  • 12,579
  • 10
  • 47
  • 69
user2783615
  • 829
  • 3
  • 11
  • 17

3 Answers3

12

I think the most straightforward way is

d[order(d$lvl,d$v1),]

which gives

   v1  v2 lvl
3 1.2 3.5   a
1 2.2 4.5   a
2 3.2 2.5   a
5 2.2 7.5   b
6 3.2 6.5   b
4 4.2 5.5   b
8 1.2 1.5   c
7 2.2 2.5   c
9 5.2 3.5   c
Frank
  • 66,179
  • 8
  • 96
  • 180
  • Thanks Frank! what if I want to extract all the rows with medians of v1 for each level? – user2783615 Sep 17 '13 at 05:07
  • This is a solution [I've seen @eddi use](http://stackoverflow.com/a/16574176/1191259): `require(data.table); DT <- data.table(d); DT[DT[,.I[ceiling(.N/2)],by=lvl]$V1]`. You can put the stuff separated by ";" on separate lines. Someone answered your question using data.table before, but I guess they deleted the answer. Anyway, I think it's a great package to use if you find yourself wanting to do things "by group" all the time (as I do). If you have another similar question, you might want to post it as a new question on SO. Space and typesetting are limited in comments. :) – Frank Sep 17 '13 at 05:12
3

Using dplyr, you can add .by_group = TRUE to arrange() to sort the column within each group. Try:

library(dplyr)
d %>% 
        group_by(lvl) %>%
        arrange(v1, .by_group = TRUE)
# output
# A tibble: 9 x 3
# Groups:   lvl [3]
     v1    v2    lvl
  <dbl> <dbl> <fctr>
1   1.2   3.5      a
2   2.2   4.5      a
3   3.2   2.5      a
4   2.2   7.5      b
5   3.2   6.5      b
6   4.2   5.5      b
7   1.2   1.5      c
8   2.2   2.5      c
9   5.2   3.5      c
nghauran
  • 6,648
  • 2
  • 20
  • 29
1

I believe this is also a legitimate solution using dplyr:

require(data.table)
require(dplyr)
require(dtplyr)

DT <- as.data.table(d)
DT %>% group_by(lvl) %>% arrange(v1)
James Hirschorn
  • 7,032
  • 5
  • 45
  • 53