2012-06-20 80 views
3

首先爲不清晰的問題標題道歉,這是一個相當具體的問題,我不知道如何在一行中輸入!將id更新爲它的parent_id,除非它有不同的值

無論如何,我的問題如下。我有一個數據框與一個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 & b都等於x,與id 1相同,但是id 3保持不變,儘管它的parent_id1,它不具有相同的屬性。

任何幫助,將不勝感激。

回答

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) 
+0

我已經更新了我的答案與文本或數字數據的工作。數據中的順序應該不重要,因爲'match'返回的是位置而不是匹配的值。 – thelatemail

1

其他人可能有一個更優雅的解決方案,但是這得到你想要的東西:

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] 
1

此更新後的版本應該上的文字或數字ID變量工作你,thelatemails答案適用於我給你的例子,但實際上我的數據框中的id不是1,2,3,4等......但更隨機,並且不包含所有數字,因此當你得到ds [匹配,]。我認爲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))) 

我認爲作品是相當麻利。

感謝

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) 
相關問題