首先为这个不清楚的问题标题道歉,这是一个非常具体的问题,我不知道如何在一行中说出来!
无论如何,我的问题如下。我有一个数据框,其中包含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}}相同,它没有相同的属性。
任何帮助都将不胜感激。
答案 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)