比较两列:逻辑 - 第2列中的第1列的值是什么?

时间:2011-12-16 21:28:42

标签: r compare set

我对如何解决这个问题感到很困惑。假设我在数据帧中有两列。一列是数字序列的顺序(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)

我的话,上面修正了更多错误......

2 个答案:

答案 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)

使用xy创建从较高数字到较低数字的映射,这些数字是同一个人。请注意,名称是一个字符串,尽管它是一串数字。

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)
}