3

我有一个标准的“可以避免循环”问题,但找不到解决方案。

我通过@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
}

我的问题

没有循环和条件,任何人都可以做到这一点吗?

4

3 回答 3

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
于 2012-05-15T22:58:37.977 回答
3

我对此的破解:

as.numeric(df[, 1])-1
于 2012-05-15T23:05:57.623 回答
2

这也发生在我身上,您可以简单地转换为一个因子,然后返回整数并减去一个:

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

如果type已经是一个因素,您可以跳过该步骤。

于 2012-05-15T23:05:10.573 回答