2012-05-15 28 views
3

我有一个标准的'can-I-avoid-a-loop'问题,但找不到解决方案。为for循环标记连续的观察块

我回答了this question by @splaisan,但我不得不在中间部分采用一些丑陋的扭曲,用for和多个if测试。我希望有人能给出一个更好的答案在这里模拟一个简单的版本...

的问题

鉴于这样的数据结构:

df <- read.table(text = 'type 
a 
a 
a 
b 
b 
c 
c 
c 
c 
d 
e', header = TRUE) 

我要找出连续相同类型的块并将它们分组标记。第一个块应该标记为0,下一个为1,依此类推。无限数量的块,每块可能只有一个成员。

type label 
    a 0 
    a 0 
    a 0 
    b 1 
    b 1 
    c 2 
    c 2 
    c 2 
    c 2 
    d 3 
    e 4 

我的解决方案

我不得不求助于for循环要做到这一点,这里是代码:

label <- 0 
df$label <- label 

# LOOP through the label column and increment the label 
# whenever a new type is found 
for (i in 2:length(df$type)) { 
    if (df$type[i-1] != df$type[i]) { label <- label + 1 } 
    df$label[i] <- label 
} 

我的问题

任何人都可以做这没有循环和条件?

+1

见'rle',最有用的r功能没有人能够找到? – joran

+0

谢谢@joran,我可以看到如何帮助!我会探索它一段时间。我的第一个努力工作,但仍然不雅。如果我管理一个可以通过的,我会发布一个答案。 – gauden

+1

只需将长度组件从'rle'输入到'rep'中的times参数中。 – joran

回答

6

使用rle

r <- rle(as.numeric(df$type)) 
df$label <- rep(seq(from=0, length=length(r$lengths)), times=r$lengths) 

不使用rle,但cumsum在那被强制为数字逻辑值。

df$label <- c(0,cumsum(df$type[-1] != df$type[-length(df$type)])) 

均可以得到:

> df 
    type label 
1  a  0 
2  a  0 
3  a  0 
4  b  1 
5  b  1 
6  c  2 
7  c  2 
8  c  2 
9  c  2 
10 d  3 
11 e  4 
2

这只是发生在我身上,以及,你可以简单地转换到一个因素,然后再回到整数和减一:

as.integer(as.factor(df$type))-1 

如果type已经是一个因素,你可以跳过这一步。

+0

+1为横向思维。 – gauden

+1

...假设任何'df $ type'单个值都不会出现在多个块中,并且它们按字母顺序出现。 –

3

我吧裂纹:

as.numeric(df[, 1])-1 
+0

+1为横向思维。 – gauden

+0

哦,这和Joran的真的一样,他打了我几秒钟。你必须转换为一个因素,因为他说明类型是不是已经如此。 –

+0

是的,你们都被我撕裂,把绿色的蜱放在哪里!我把它留给布赖恩,因为他有第一个完整的工作版本。尽管如此,非常感谢。 – gauden