【问题标题】:Labeling contiguous chunks of observations without a for loop在没有 for 循环的情况下标记连续的观察块
【发布时间】:2012-05-23 11:57:25
【问题描述】:

我有一个标准的“can-I-avoid-a-loop”问题,但找不到解决方案。

我回答了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
}

我的问题

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

【问题讨论】:

  • ?rle,最有用的R函数,没人能找到。
  • 谢谢@joran,我知道这会有什么帮助!我会探索一段时间。我的第一次努力正在奏效,但仍然不够优雅。如果我管理一个可以接受的答案,我会发布一个答案。
  • 只需将 rle 中的长度分量输入到 rep 中的时间参数中。

标签: r


【解决方案1】:

使用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.numeric(df[, 1])-1
    

    【讨论】:

    • 哦,这真的和乔兰的一样,他比我多几秒钟。如果类型不是这样,你必须转换为他所说的因子。
    • 是的,你们都让我不知道在哪里放置绿色勾号!考虑到他有第一个完整的工作版本,我把它留给了布赖恩。不过,非常感谢大家。
    • 我认为布赖恩的解决方案更通用。不要在 Joran 击败我时打我,他的表现与我的基本相同,但更好。
    【解决方案3】:

    这也是我刚想到的,您可以简单地转换为一个因子,然后再转换为整数并减去一个:

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

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

    【讨论】:

    • ...假设df$type 的任何单个值不会出现在一个以上的块中并且它们按字母顺序出现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    相关资源
    最近更新 更多