将id更新为其parent_id,除非它具有不同的值

时间:2012-06-20 18:56:01

标签: r

首先为这个不清楚的问题标题道歉,这是一个非常具体的问题,我不知道如何在一行中说出来!

无论如何,我的问题如下。我有一个数据框,其中包含id,父ID和两个值,比如a和b。我想将行的id更新为其parent_id,除非它的值不等于其parent_id的值。

例如,我说我有桌子:

id parent_id a b  
1    0       x x
2    1       x x
3    1       x y
4    0       y y
5    4       x x 
6    1       x x
7    4       y y

可以使用代码

生成
 x <- data.frame('id' = c(1,2,3,4,5,6,7),
                 'parent_id' = c(0,1,1,0,4,1,4),
                 'a' = c('x','x','x','y','x','x','y'),
                 'b' = c('x','x','y','y','x','x','y'))

这应该成为:

id parent_id a b
1    0       x x
1    1       x x
3    1       x y
4    0       y y
5    4       x x
1    1       x x
4    4       y y

所以id 2已成为1,因为它是parent_id,属性为a&amp; b等于x,与id 1相同,但id 3与parent_id 1 {{1}}相同,它没有相同的属性。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:1)

其他人可能会有一个更优雅的解决方案,但这可以得到你想要的东西:

# list of a-b pairs for parent_id
parent.id.ab <- with(x, lapply(parent_id, FUN=function(y) c(a[id==y], b[id==y])))

# list of a-b pairs for id
id.ab <- with(x, mapply(function(y,z) c(y,z), a, b, SIMPLIFY=FALSE))

# condition is a vector of TRUE/FALSE, TRUE if the parent_id a-b pair equals the id a-b.
# When the parent_id is 0, its a-b pair is integer(0). Since all(logical(0)) is TRUE,
# we only use all(z == y) when z and y have the same length.
condition <- mapply(function(z,y) if (length(z) == length(y)) all(z == y) else FALSE, 
                    parent.id.ab, id.ab)

x$id <- ifelse(condition, x$parent_id, x$id)

答案 1 :(得分:1)

此更新版本应适用于文本或数字ID变量:

vars <- c("a","b")
matches <- apply(x[vars]==x[match(x$parent_id,x$id),][vars],1,all)
x$id[matches==TRUE & is.na(matches)==FALSE] <- x$parent_id[matches==TRUE & is.na(matches)==FALSE]

答案 2 :(得分:1)

感谢你们两位,thelatemails的答案适用于我给你的例子,但实际上我的数据框中的id不是1,2,3,4等...但是更随机并且不包含所有数字所以当你得到ds [matches,]时代码就会掉下来。我认为mplourde的答案可以解决问题,但我最终使用以下代码完成了它:

  betValues <- with(x, paste(id, a, b, sep="-"))

  x[, 'id'] <- with(x, ifelse(parent_id== 0, id, 
          ifelse(!paste(parent_id, a, b, sep="-") %in%  betValues, id, parent_id)))

我认为它很有效且非常快速。

由于

答案 3 :(得分:0)

有趣的问题,我的看法:

own.idx        <- seq_len(nrow(x))
parent.idx     <- match(x$parent_id, x$id)
matches.parent <- mapply(function(i,j)!is.na(j) && all(x[i, c("a", "b")] ==
                                                       x[j, c("a", "b")]),
                         own.idx, parent.idx)

x$id <- ifelse(matches.parent, x$parent_id, x$id)