Используя (обновленный) пример, который вы дали
x <- c(1,2,3,4,5,6,7,8,9,10)
y <- c(-1,-1,-1,-1,1,-1,1,-1,3,4)
group <- c(1,1,1,2,2,2,3,3,3,3)
DF <- data.frame(x,y,group)
Используйте x
и y
, чтобы создать отображение из более высоких чисел в более низкие числа, которые являются одним и тем же человеком.Обратите внимание, что names - это строка, несмотря на то, что она представляет собой строку цифр.
bottom.df <- DF[DF$y==-1,]
mapdown.df <- DF[DF$y!=-1,]
mapdown <- c(mapdown.df$y, bottom.df$x)
names(mapdown) <- c(mapdown.df$x, bottom.df$x)
Мы не знаем, сколько раз может потребоваться, чтобы все свелось к наименьшему числу, поэтому нужно использовать while
loop.
oldx <- DF$x
newx <- mapdown[as.character(oldx)]
while(any(oldx != newx)) {
oldx = newx
newx = mapdown[as.character(oldx)]
}
Результатом является группа, к которой он принадлежит, имена с наименьшим номером из этого набора.
DF$id <- unname(newx)
Получить членство в группе сложнее.Использование reshape2
для преобразования этого в широкоформатный формат (по одному столбцу на группу), где столбец равен «1», если в нем что-то было, и «0», если нет.
library("reshape2")
wide <- dcast(DF, id~group, value.var="id",
fun.aggregate=function(x){if(length(x)>0){"1"}else{"0"}})
Наконец, вставьте этиЧленство «0» / «1» вместе, чтобы получить переменную группировки, которую вы описали.
wide$grouping = apply(wide[,-1], 1, paste, collapse="")
Результат:
> wide
id 1 2 3 grouping
1 1 1 1 1 111
2 2 1 0 0 100
3 3 1 0 1 101
4 4 0 1 1 011
5 6 0 1 0 010
6 8 0 0 1 001
Пока нет «бонуса».
РЕДАКТИРОВАТЬ:
Чтобы получить информацию о бонусе, помогает повторить сопоставление, чтобы сохранить все.Если у вас много дел, это может быть медленным.
Замените часть oldx
/ newx
на:
iterx <- matrix(DF$x, ncol=1)
iterx <- cbind(iterx, mapdown[as.character(iterx[,1])])
while(any(iterx[,ncol(iterx)]!=iterx[,ncol(iterx)-1])) {
iterx <- cbind(iterx, mapdown[as.character(iterx[,ncol(iterx)])])
}
DF$id <- iterx[,ncol(iterx)]
Для создания бонусных данных, вы можете использовать
bonus <- tapply(iterx[,1], iterx[,ncol(iterx)], paste, collapse=",")
wide$bonus <- bonus[as.character(wide$id)]
Что дает:
> wide
id 1 2 3 grouping bonus
1 1 1 1 1 111 1,5,7
2 2 1 0 0 100 2
3 3 1 0 1 101 3,9
4 4 0 1 1 011 4,10
5 6 0 1 0 010 6
6 8 0 0 1 001 8
Обратите внимание, что это не то же самое, что ваш пример вывода, но я не думаю, что ваш пример вывода является правильным (как вы можете иметь grouping_history
из "000"?)
РЕДАКТИРОВАТЬ:
Теперь он согласен.