Assign unique ID based on two columns

We can do this in base R without doing any group by operation

df$ID <- cumsum(!duplicated(df[1:2]))
df
#   School Student Year ID
#1      A      10 1999  1
#2      A      10 2000  1
#3      A      20 1999  2
#4      A      20 2000  2
#5      A      20 2001  2
#6      B      10 1999  3
#7      B      10 2000  3

NOTE: Assuming that 'School' and 'Student' are ordered


Or using tidyverse

library(dplyr)
df %>% 
    mutate(ID = group_indices_(df, .dots=c("School", "Student"))) 
#  School Student Year ID
#1      A      10 1999  1
#2      A      10 2000  1
#3      A      20 1999  2
#4      A      20 2000  2
#5      A      20 2001  2
#6      B      10 1999  3
#7      B      10 2000  3

As @radek mentioned, in the recent version (dplyr_0.8.0), we get the notification that group_indices_ is deprecated, instead use group_indices

df %>% 
   mutate(ID = group_indices(., School, Student))

Group by School and Student, then assign group id to ID variable.

library('data.table')
df[, ID := .GRP, by = .(School, Student)]

#    School Student Year ID
# 1:      A      10 1999  1
# 2:      A      10 2000  1
# 3:      A      20 1999  2
# 4:      A      20 2000  2
# 5:      A      20 2001  2
# 6:      B      10 1999  3
# 7:      B      10 2000  3

Data:

df <- fread('School Student  Year  
A         10    1999
      A         10    2000
      A         20    1999
      A         20    2000
      A         20    2001
      B         10    1999
      B         10    2000')