Multiple use of setdiff () for consecutive groups without loops

I would like setdiffbetween successive groups without a loop, if possible, using a data type or a function of the apply family.

Dataframe df:

   id group
1  L1     1
2  L2     1
3  L1     2
4  L3     2
5  L4     2
6  L3     3
7  L5     3
8  L6     3
9  L1     4
10 L4     4
11 L2     5

I want to know how many new identifiers exist between consecutive groups. So, for example, if we compare groups 1 and 2, there are two new identifiers: L3and L4, therefore, it returns 2 (not setdiffdirectly, but with length()), if we compare group 2 and 3, L5and L6are news identifiers, therefore it returns 2 and etc.

Expected results:

new_id
  2
  2
  2
  1

Data:

structure(list(id = structure(c(1L, 2L, 1L, 3L, 4L, 3L, 5L, 6L, 
1L, 4L, 2L), .Label = c("L1", "L2", "L3", "L4", "L5", "L6"), class = "factor"), 
    group = c(1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5)), class = "data.frame", row.names = c(NA, 
-11L), .Names = c("id", "group"))
+4
source share
4 answers

mapply:

lst <- with(df, split(id, group))   
mapply(function(x, y) length(setdiff(y, x)), head(lst, -1), tail(lst, -1))

#1 2 3 4 
#2 2 2 1 
+3

data.table merge. , data.frame dt:

library(data.table)

setDT(dt)
dt2 <- copy(dt)[, group := group + 1]

merge(
    dt, dt2, by = 'group', allow.cartesian = T
)[, .(n = length(setdiff(id.x, id.y))), by = group]

#    group n
# 1:     2 2
# 2:     3 2
# 3:     4 2
# 4:     5 1
+2
L = split(d, d$group) #Split data ('d') by group and create a list

#use lapply to access 'id' for each sub group in the list and obtain setdiff
sapply(2:length(L), function(i)
     setNames(length(setdiff(L[[i]][,1], L[[i-1]][,1])),
     nm = paste(names(L)[i], names(L)[i-1], sep = "-")))
#2-1 3-2 4-3 5-4 
#  2   2   2   1 
+1
source

You can use the Reducepairwise comparison in the list to start the comparison function. for instance

xx<-Reduce(function(a, b) {
    x <- setdiff(b$id, a$id); 
    list(id=b$id, new=x, newcount=length(x))
  }, split(df, df$group), 
  acc=TRUE)[-1]

Then you can get the number of new items with

sapply(xx, '[[', "newcount")

and you can get new values ​​with

sapply(xx, '[[', "new")
+1
source

Source: https://habr.com/ru/post/1674218/


All Articles