We can use Map after splitting each of the columns into , combine their setdiff , paste , set the names of the list output with the column "ID", stack it to 'data.frame' and set names 'ID' and 'Output' for the columns.
setNames(stack(setNames(Map(function(x,y) toString(setdiff(x,y)), strsplit(as.character(df1$variable1), ","), strsplit(as.character(df1$variable2), ",")), df1$ID))[2:1], c("ID", "Output"))
Or a compact option would be
library(splitstackshape) cSplit(df1, 2:3, ",", "long")[, .(Output = toString(setdiff(variable1, variable2))) , ID] # ID Output #1: 1 b, d #2: 2 g, f #3: 3 p, m, n
source share