3

首先,为可怜的不清楚的问题标题道歉,这是一个非常具体的问题,我不知道如何用一行来表达!

无论如何,我的问题如下。我有一个带有 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

所以id2 变成了 1,因为它是parent_id,并且是属性a&b都等于x,与 1 相同id,但是id3 保持不变,尽管它parent_id1,但它不具有相同的属性。

任何帮助,将不胜感激。

4

4 回答 4

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)
于 2012-06-20T19:28:34.137 回答
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]
于 2012-06-20T22:36:08.910 回答
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)))

我认为这很有效,而且非常快速和整洁。

谢谢

于 2012-06-21T10:33:49.037 回答
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)
于 2012-07-08T23:04:00.297 回答