1
$\begingroup$

I have a random created dataframe named a:

  group marks  upd
1     a     2   up
2     b     3   up
3     a     4 down
4     b     5   up
5     a     6 down
6     c     7   up
7     a     8 down

I wanted to subset it with only group='a' and marks in decreasing order of a. I used this query but the marks are not arranged in decreasing order. What is the error in my code?

Here is my code and output:

> a[a$group=="a" & a$marks[order(a$marks,decreasing=T)],]
  group marks  upd
1     a     2   up
3     a     4 down
5     a     6 down
7     a     8 down

Warning message:
In a$group == "a" & order(a$marks, decreasing = TRUE)[1:3] :
  longer object length is not a multiple of shorter object length
$\endgroup$
6
  • $\begingroup$ Could you please give some sample data, IM not clear on what your data looks like. $\endgroup$
    – Marcus D
    Apr 25, 2016 at 18:48
  • $\begingroup$ I added the table here but it just came in one line.. I dont know how to get that in a table.. :( $\endgroup$
    – pinky
    Apr 25, 2016 at 18:54
  • $\begingroup$ Is it okay if I can suggest an alternate solution (a simpler and a nice looking one)? $\endgroup$
    – Dawny33
    Apr 26, 2016 at 2:33
  • $\begingroup$ @Dawny: Sure... $\endgroup$
    – pinky
    Apr 26, 2016 at 3:15
  • $\begingroup$ Never mind. Luke has included it in the answer. Use dplyr when manipulating data. It is much simpler and looks more elegant :) $\endgroup$
    – Dawny33
    Apr 26, 2016 at 4:57

2 Answers 2

2
$\begingroup$

a$group=="a" gives

# [1]  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE

and a$marks[order(a$marks,decreasing=T)] gives

# [1] 8 7 6 5 4 3 2

Combining those to using a logical and (&) does not make much sense here. TRUE & 8 is TRUE - the subsetting may accidentally work. But you want order to look at your subset only, not at all rows in a.

Try for instance

newa <- a[a$group=="a", ] 
newa[order(newa$marks, decreasing = TRUE), ]
#   group marks  upd
# 7     a     8 down
# 5     a     6 down
# 3     a     4 down
# 1     a     2   up

or, more convenient and readable:

library(dplyr)
a %>% filter(group=="a") %>% arrange(desc(marks))
$\endgroup$
3
  • $\begingroup$ That was a good explanation. thank you so much. It solved my problem. And one more ques: if I just need top three marks from this output, what would the code be? $\endgroup$
    – pinky
    Apr 26, 2016 at 1:36
  • $\begingroup$ I tried to put a function here: groups=unique(a$group) check=function(x) { subdata=a[a$group==x,] data=subdata[order(subdata$marks,decreasing=TRUE)[1:3],] data } this was my ouput- check(groups) group marks upd 6 c 7 up 2 b 3 up 1 a 2 up . Here, it just gave top 1 record of each group. But I wanted output to display all the top 3 records of marks of each group. $\endgroup$
    – pinky
    Apr 26, 2016 at 2:08
  • $\begingroup$ E.g. a <- a[order(a$group, -a$marks), ];do.call(rbind, lapply(split(a, a$group), head, 3)) or a %>% arrange(group, desc(marks)) %>% group_by(group) %>% slice(1:3) $\endgroup$
    – lukeA
    Apr 26, 2016 at 8:32
1
$\begingroup$

without Dplyr, you could use

b<- a[a$group=="a",]       
c<- b[b$marks[order(b$marks,decreasing=T),]  

this because you are referring to the order of $b$ inherited from a, and you can not use the ranking of the items of the list a to indicate where the rows of b should go.

If you need the first three items in there, take

head(c,3) 
$\endgroup$
2
  • $\begingroup$ because you are referring to the order of $b$, not of $a$ <-- Wrong. She wants the order of a $\endgroup$
    – Dawny33
    Apr 26, 2016 at 11:08
  • $\begingroup$ b has only a subset of the rows of a, so it is shorter. Therefore the sort order needs to be as long as b, not as long as a. that is what I meant. I updated the answer to clarify. By the way, sorting is a heavy process, so t is better to sort the shorter vector rather than the longer one, if the datasets is large. $\endgroup$
    – vinnief
    Apr 26, 2016 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.