我对如何解决这个问题感到很困惑。假设我在数据帧中有两列。一列是数字序列的顺序(x),另一列是从第一列指定的值,或-1(y)。这些是匹配实验的结果,其目标是查看是否拍摄了同一个人的多张照片。在下面的示例中,有10张照片,但有6张是独特的个人。在y列中,如果存在匹配,则报告相应的x。 y为-1表示没有匹配(也可能是NAs)。如果每个人的照片超过2张,则匹配#将是最近的记录(照片1,5和7是下面的同一个人)。该组是照片拍摄的时间段(组内没有匹配!)。希望我有这个例子:
x <- c(1,2,3,4,5,6,7,8,9,10)
y <- c(-1,-1,-1,-1,1,-1,1,-1,2,4)
group <- c(1,1,1,2,2,2,3,3,3,3)
DF <- data.frame(x,y,group)
我想创建一个新变量来命名唯一个体,并且每个人都有一个单行的最终数据集(即只有6行而不是10行),还包括组信息。即如果一个人在所有三个组中,则可能存在值“111”或者如果仅在第一组和最后一组中它将是“101”。有什么提示吗?
感谢您询问结果数据集。根据我给出的实际数字,我意识到我的小组解释很糟糕,所以我稍微改变了结果。奖金也很好,但并不重要。
name <- c(1,2,3,4,6,8)
group_history <- as.character(c('111','101','100','011','010','001'))
bonus <- as.character(c('1,5,7','2,9','3','4,10','6','8'))
results_I_want <- data.frame(name,group_history,bonus)
我的话,上面修正了更多错误......
答案 0 :(得分:2)
使用您提供的(更新)示例
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
创建从较高数字到较低数字的映射,这些数字是同一个人。请注意,名称是一个字符串,尽管它是一串数字。
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
循环。
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”?)
编辑:
现在它同意了。
答案 1 :(得分:1)
奖金变量的另一种解决方案
f_bonus <- function(data=df){
data_a <- subset(data,y== -1,select=x)
data_a$pos <- seq(nrow(data_a))
data_b <- subset(df,y!= -1,select=c(x,y))
data_b$pos <- match(data_b$y, data_a$x)
data_t <- rbind(data_a,data_b[-2])
data_t <- with(data_t,tapply(x,pos,paste,sep="",collapse=","))
return(data_t)
}