2012-10-20 17 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) 
}) 
相关问题