2016-03-17 29 views
2

我似乎已經無意中發現了我無法解釋的一個mutate/lag/ifelse行爲。我有以下(簡化的)數據幀:延遲不會看到突變對前一行的影響

test <- data.frame(type = c("START", "END", "START", "START", "START", "START", "END"), 
        stringsAsFactors = FALSE) 

> test 

    type 
1 START 
2 END 
3 START 
4 START 
5 START 
6 START 
7 START 
8 END 

我想修改列type以具有交替的STARTEND雙序列(請注意,在test數據幀僅START序列是可能的, END永不重複):

> desired 

    type 
1 START 
2 END 
3 START 
4 END 
5 START 
6 END 
7 START 
8 END 

我以爲我可以實現我用下面的代碼的目標:

test %>% 
mutate(type = ifelse(type == "START" & 
         dplyr::lag(type, n=1, default="END") == "START" & 
         dplyr::lead(type, n=1, default="END") == "START", "END" , type)) 

代碼應檢測其中STARTSTART之前和之後一START行,在這種情況下,type值改變爲END。在此更改之後,以下START(行號5的test)不應匹配,因爲其先前的type值現在爲END。不幸的是,該命令的輸出如下:

type 
1 START 
2 END 
3 START 
4 END 
5 END 
6 END 
7 START 
8 END 

這就像通過lag看到的值不會受發生變異。這是應該如何工作?有沒有辦法以lag在前一行看到mutate的影響的方式對其進行編碼?

版本,R 3.2.3版(2015年12月10日),dplyr_0.4.3

UPDATE:爲什麼上面的代碼不工作是由保羅Rougieux下面解釋其原因是:超前和滯後被固定並沒有考慮到進一步的修改。所以我想正確的答案是「它不能直接使用dplyr來完成」。分別在mutate()

+0

這是否有使用方案和包你現在可以解決或者是你開放給其他的解決方案(使用其他功能)? – DatamineR

+0

一般來說,我寧願堅持dplyr,因爲我使用它很多,我想了解這種行爲是否「正常」。但是如果你有一個依賴於其他功能的解決方案,那仍然會有很大的幫助。 – domi

+0

'test $ type < - rep(unique(test $ type),length.out = nrow(test))'? – mtoto

回答

1

定義滯後和鉛的變量會告訴你,你對ifelse(type == "START" & lag == "START" & lead == "START", "END" , type)調用行不通:

test <- data.frame(type = c("START", "END", "START", "START", "START", "START", "END"), stringsAsFactors = FALSE) 
test %>% 
    mutate(lag = dplyr::lag(type, n=1, default="END"), 
      lead = dplyr::lead(type, n=1, default="END"), 
      type2 = ifelse(type == "START" & lag == "START" & lead == "START", 
          "END" , type)) 

# type lag lead type2 
#1 START END END START 
#2 END START START END 
#3 START END START START 
#4 START START START END 
#5 START START START END 
#6 START START END START 
#7 END START END END 

dplyr::mutate()修改矢量作爲一個整體。先導和滯後是固定的,不考慮對矢量的進一步修改。你想要的是這種情況下的`Reduce()函數。檢查幫助(減少)。

+0

是的,我知道。這就是我所說的「滯後的價值不受變異的影響」。我不明白的是爲什麼,以及是否有辦法讓它像我期待的那樣行事。 – domi

0

這個怎麼樣?

test$type[test$type != c("START", "END")] <- 
ifelse(test$type[test$type != c("START", "END")] == "START", "END", "START") 

test 
    type 
1 START 
2 END 
3 START 
4 END 
5 START 
6 END 
7 START 

(這些警告可以忽略不計)

+0

你的代碼工作得很好。我對Paul Rougieux的回答給予了更多的價值(即使它是部分的,也就是說,沒有提供問題的確切解決方案),因爲他對dplyr軟件包進行了構建。我不知道導致/滯後不考慮修改,這就是爲什麼我的代碼不起作用。不過,非常感謝您的回答。 – domi

+0

爲了避免警告「更長的對象長度不是更短的對象長度的倍數」,您可以創建一個長度相同的對象。target < - rep(c(「START」,「END」),ceiling(nrow(test)/ 2))[c(1:nrow(test))]''然後在比較中使用它'test $ type [test $ type!= goal] < - ifelse(test $ type [test $ type!= goal] == 「開始」,「結束」,「開始」)。它看起來像[重言式](https://en.wikipedia.org/wiki/Tautology_%28logic%29),「goal」將始終等於'test $ type'。 –