2012-10-20 18 views
3

我試圖將幾個連續的行分組(並賦予它們相同的值),同時將某些行留空(當某些條件未滿足時)。將序列中的值賦給一組連續的行,留下一些行爲空

我的數據是位置(xy座標),測量它們的日期/時間以及測量之間的時間跨度。不知何故簡化,它們看起來就像這樣:

ID X  Y  Time Span 
1 3445 7671 0:00 - 
2 3312 7677 4:00 4 
3 3309 7680 12:00 8 
4 3299 7681 16:00 4 
5 3243 7655 20:00 4 
6 3222 7612 4:00 8 
7 3260 7633 0:00 4 
8 3254 7641 8:00 8 
9 3230 7612 0:00 16 
10 3203 7656 4:00 4 
11 3202 7678 8:00 4 
12 3159 7609 20:00 12 
... 

我想一個值分配給被4個小時的時間跨度內測量的位置每一個序列,使我的數據是這樣的:

ID X  Y  Time Span Sequence 
1 3445 7671 0:00 -  - 
2 3312 7677 4:00 4  1 
3 3309 7680 12:00 8  NA 
4 3299 7681 16:00 4  2 
5 3243 7655 20:00 4  2 
6 3222 7612 4:00 8  NA 
7 3260 7633 0:00 4  3 
8 3254 7641 8:00 8  NA 
9 3230 7612 0:00 16 NA 
10 3203 7656 4:00 4  4 
11 3202 7678 8:00 4  4 
12 3159 7609 20:00 12 NA 

我試過幾種算法用循環「爲」加「ifelse」條件,如:

Sequence <- for (i in 1:max(ID)) { 
ifelse (Span <= 4, i+1, "NA") 
} 

沒有任何的運氣。我知道我的嘗試是不正確的,但是我的編程技巧是非常基本的,並且我還沒有發現任何類似的問題。

任何想法將不勝感激!

+0

你的僞代碼表示,如果'跨度<= 4,'Sequence'應該是'我+ 1'其中'i'是行數。然而,在你想要的輸出中,你有多行具有相同的「序列」值? (例如具有'序列'2的兩行)。那麼,你想如何爲行分配'Sequence'值? –

回答

0
count = 0 
for (i in 1:max(ID)) { 
     Sequence[i] = ifelse(Span[i] <= 4, count <- count+1, NA) 
} 
+0

這將字符串賦值爲「NA」而不是值「NA」。另外,'ifelse'是矢量化的,所以你最好使用'my_df $ Sequence < - ifelse(my_df $ span <= 4,(1:max(my_df $ ID))+ 1,NA)',這相當於你寫的代碼。然而,所有這些都是沒有意義的,因爲'count + 1'出現*不是OP想要放入'Sequence'列的內容。 –

+0

@ mathematical.coffee thx。我只是糾正它。 – liuminzhao

6

這裏是一個稍長的一個襯裏:

ifelse(x <- DF$Span == 4, cumsum(c(head(x, 1), tail(x, -1) - head(x, -1) == 1)), NA) 
# [1] NA 1 NA 2 2 NA 3 NA NA 4 4 NA 

說明:

  • x是TRUE/FALSE表示在Span4的向量。
  • tail(x, -1)是寫作的一種安全的方式x[2:length(x)]
  • head(x, -1)是寫x[1:(length(x)-1)]
  • tail(x, -1) - head(x, -1) == 1的一種安全的方式是TRUE/FALSE表示在我們從Span != 4Span == 4的載體。
  • 由於上面的向量是比x短的一個元素,因此我在其前面加了head(x, 1)head(x, 1)是一種安全的寫作方式x[1]
  • 然後我拿cumsum,因此它將向量TRUE/FALSE轉換成遞增整數的向量:其中Span!=4跳轉到==4它增加1,否則保持不變。
  • 所有內容都包含在ifelse中,因此您只能看到x爲TRUE的數字,即Span == 4
+0

創意方法+1 –

+0

@ flodel,你可以在答案上稍微擴展一點,解釋你正在做什麼的邏輯。這可能會使您的答案更易於搜索,從而對於將來也有類似問題的其他人更有用。 – A5C1D2H2I1M1N2O1R2T1

+0

@mrdwab,只因爲你問了!否則,我認爲它需要一點魔力:-) – flodel

1

這是另一種使用rlerep的替代方案。我們假設您的data.frame被命名爲「test」。

首先,初始化您的「序列」列,填入NA

test$Sequence <- NA 

二,指定您匹配的條件,在這種情況下,test$Span == 4

x <- test$Span == 4 

三,使用rle的輸出(lengthsvalues)的組合來獲得序列中的每個新的運行出現的次數。

spanSeq <- rle(x)$lengths[rle(x)$values == TRUE] 

最後,使用reptimes參數設置爲在步驟3中的子集根據由test$Span == 4匹配索引中的test$Sequence所需的值而獲得的結果,並使用新序列替換它們。

test$Sequence[x] <- rep(seq_along(spanSeq), times = spanSeq) 
test 
# ID X Y Time Span Sequence 
# 1 1 3445 7671 0:00 -  NA 
# 2 2 3312 7677 4:00 4  1 
# 3 3 3309 7680 12:00 8  NA 
# 4 4 3299 7681 16:00 4  2 
# 5 5 3243 7655 20:00 4  2 
# 6 6 3222 7612 4:00 8  NA 
# 7 7 3260 7633 0:00 4  3 
# 8 8 3254 7641 8:00 8  NA 
# 9 9 3230 7612 0:00 16  NA 
# 10 10 3203 7656 4:00 4  4 
# 11 11 3202 7678 8:00 4  4 
# 12 12 3159 7609 20:00 12  NA 

一旦你理解所涉及的步驟,你也可以用within()這樣直接。下面將給你相同的結果:

within(test, { 
    Sequence <- NA 
    spanSeq <- rle(Span == 4)$lengths[rle(Span == 4)$values == TRUE] 
    Sequence[Span == 4] <- rep(seq_along(spanSeq), times = spanSeq) 
    rm(spanSeq) 
}) 
相關問題