我正在尝试将几个连续的行分组(并为它们分配相同的值),同时将一些行留空(当某个条件未满足时)。
我的数据是位置(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
我尝试了几种带有“for”循环加上“ifelse”条件的算法,如:
Sequence <- for (i in 1:max(ID)) {
ifelse (Span <= 4, i+1, "NA")
}
没有任何运气。我知道我的尝试不正确,但我的编程技巧非常基本,我在网上没有发现任何类似的问题。
任何想法都会非常感激!
答案 0 :(得分: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向量,显示Span
4
的位置。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 != 4
到Span == 4
的位置。x
短的元素,所以我在它前面添加了head(x, 1)
。 head(x, 1)
是一种安全的撰写方式x[1]
。cumsum
因此它将向量TRUE / FALSE转换为增加整数的向量:其中Span
从!=4
跳到==4
它增加1 ,否则保持不变。ifelse
中,因此您只能看到x
为真的数字,即Span == 4
。 答案 1 :(得分:1)
以下是使用rle
和rep
的另一种选择。我们假设您的data.frame
被命名为“test”。
首先,初始化您的“序列”列,并使用NA
填充。
test$Sequence <- NA
其次,指定您匹配的条件,在本例中为test$Span == 4
。
x <- test$Span == 4
第三,使用rle
输出(lengths
和values
)的组合来获取序列中每次新运行的次数。
spanSeq <- rle(x)$lengths[rle(x)$values == TRUE]
最后,使用rep
并将times
参数设置为步骤3中获得的结果。根据test$Sequence
匹配的索引子集test$Span == 4
所需的值,并用你的新序列替换它们。
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)
})
答案 2 :(得分:0)
count = 0
for (i in 1:max(ID)) {
Sequence[i] = ifelse(Span[i] <= 4, count <- count+1, NA)
}