MariKo
MariKo

Reputation: 305

Rank and order in loop for different conditions for different subjects R

I have a data frame df:

Subject     RT      Trial       Block
1           234     1           1
1           563     2           1
1           234     3           1
1           234     1           2
1           467     2           2
1           234     3           2
1           543     1           3
1           466     2           3
1           111     3           3
2           343     1           1
2           44      2           1
2           223     3           1
2           324     1           2
2           34      2           2
2           242     3           2
2           54      1           3
2           656     2           3
2           345     3           3

I want to assign ranks of RTs per subject per each block, so the df would look like this:

Subject     RT      Trial       Block    Rank
1           234     1           1        1
1           563     2           1        3
1           239     3           1        2
1           230     1           2        1
1           467     2           2        3
1           234     3           2        2
1           543     1           3        3
1           466     2           3        2
1           111     3           3        1
2           343     1           1        3
2           44      2           1        1
2           223     3           1        2
2           324     1           2        3
2           34      2           2        1
2           242     3           2        2
2           54      1           3        1
2           656     2           3        3
2           345     3           3        2

And then I also want to sort the data frame by the content of the Rank column.

I have the code for one participant that looks like this:

df$Rank <- ave( df$RTs, FUN=rank ) # introduce ranks for Rts
df<- df[order(df$Rank),] # sorting a data frame by the contents of the Rank column

I try to loop this code but I think that I enter an infinite loop with that:

for (sno in df$Subject){
  for (bno in df$Block){
   ss <- subset(df, Subject == sno & Block == bno)
   df$Rank <- ave( df$RT, FUN=rank )
   df<- df[order(df$Rank),]
}

What is wrong with my loop? Or maybe there is a better way with functions to do it?

Upvotes: 1

Views: 958

Answers (1)

akrun
akrun

Reputation: 887223

With dplyr, we group by 'Subject', 'Block', create a 'Rank' column by using one of the ranking functions (dense_rank/min_rank), and arrange in increasing order.

library(dplyr)
df %>% 
  group_by(Subject, Block) %>% 
  mutate(Rank = dense_rank(RT)) %>%
  arrange(Subject, Block, Rank)
#    Subject    RT Trial Block  Rank
#     (int) (int) (int) (int) (int)
#1        1   234     1     1     1
#2        1   239     3     1     2
#3        1   563     2     1     3
#4        1   230     1     2     1
#5        1   234     3     2     2
#6        1   467     2     2     3
#7        1   111     3     3     1
#8        1   466     2     3     2
#9        1   543     1     3     3
#10       2    44     2     1     1
#11       2   223     3     1     2
#12       2   343     1     1     3
#13       2    34     2     2     1
#14       2   242     3     2     2
#15       2   324     1     2     3
#16       2    54     1     3     1
#17       2   345     3     3     2
#18       2   656     2     3     3

In the OP's code, there are couple of things that can be changed.

  1. With ave, there is no need for a nested for loop
  2. The output from the nested loop is assigned to create 'Rank' column so that the previous output gets overwritten.

If we are using ave

df$Rank <- with(df, ave(RT, Subject, Block, FUN=rank)) 
df[do.call(order, df[c('Subject', 'Block', 'Rank')]),]

Upvotes: 2

Related Questions