如何检测条件何时连续发生 3 次具有优先级?

How to detect when conditions happen 3 times in a row having priorities?

我已经创建了下一个可重现的最小示例来模拟我的问题。

我有一个 tibbles 列表,在这个例子中有 50 个,我想将它们分为四个不同的类别。

为了对它们进行分类,我想将类别的优先级从 4 降到 1。

如果值 4 出现但连续 3 次都没有出现,我想看看下次值 4 出现时是否出现。如果整个序列都没有发生,那么我想对值 3 做同样的事情,依此类推。

我的代码的问题是,当第一个值 4 没有预期的长度时,然后检查值 3,如果它是真的,我将没有机会将一个可能有的 tibble 归类为 4其他值 4 具有进一步索引中预期的长度。

我已经使用 rle() 函数获取值和它们连续出现的次数。

我知道 for 的 bucles 不是最好的解决方案,没有它们并且没有 rle() 可能有更简单的方法来解决这个问题。使用 python 的解决方案也会有所帮助!

valueA=replicate(50, tibble(floor(runif(800,min=1, max=5))))
valueB=list(list())
for (i in seq_along(valueA)){
  valueB[[i]]=rle(valueA[[i]]) 
}

cat=""
for (i in seq_along(valueB)){
  for (j in seq(valueB[[i]][[1]])){
    if (valueB[[i]]$values[j] == 4){
      if (valueB[[i]]$lengths[j] > 3){
        cat[i] = "four"
      }
    } else if (valueB[[i]]$values[j] == 3){
      if (valueB[[i]]$lengths[j] > 3){
        cat[i] = "three"
      }
    }else if (valueB[[i]]$values[j] == 2){
      if (valueB[[i]]$lengths[j] > 3){
        cat[i] = "two"
      }
    } else if (valueB[[i]]$values[j] == 1){
      if (valueB[[i]]$lengths[j] > 3){
        cat[i] = "one"
      }
    }
  }
}

为了澄清问题,我展示了我在这种情况下得到的结果:

> cat
 [1] "two"   "two"   "one"   "three" "one"   "three" "two"   "two"   "four"  "two"   "three" "three" "three" "two"   "three"
[16] "four"  "two"   "four"  "four"  "two"   "two"   "four"  "three" "two"   "three" "two"   "two"   "one"   "three" "four" 
[31] "four"  "three" "one"   "one"   "three" "one"   "two"   "one"   "four"  "two"   "one"   "four"  "one"   "two"   "two"  
[46] "three" "three" "three" "four"  "three"

对于第一个小标题,它说这是第二类,但检查小标题:

valueA[[1]]
  [1] 4 2 3 1 3 1 2 4 4 3 3 2 2 3 4 3 3 3 1 3 4 4 4 2 1 2 4 1 1 1 2 1 4 4 3 3 4 3 1 3 4 2 4 2 1 2 4 1 2 4 2 1 1 2 4 1 1 4 2 3 3
 [62] 2 3 1 2 3 1 4 3 2 1 3 1 4 2 3 3 2 3 1 1 3 4 2 3 1 1 1 4 4 1 4 2 4 4 1 4 1 1 4 1 4 3 3 4 2 4 2 1 1 2 1 4 1 3 1 3 2 3 2 4 2
[123] 3 2 4 1 4 3 1 2 3 2 1 2 3 1 4 4 2 1 4 4 1 3 1 4 1 4 3 2 1 3 4 4 1 2 2 1 1 1 1 3 1 3 2 3 2 2 1 3 2 1 1 2 3 4 2 3 4 2 1 3 2
[184] 4 2 1 1 1 2 1 3 3 2 3 2 2 1 1 1 1 3 1 1 2 4 1 4 1 4 2 3 2 1 2 3 3 2 4 3 2 3 1 3 3 2 1 3 3 2 4 4 4 4 2 3 2 2 2 2 3 4 3 2 3
[245] 3 3 1 4 4 1 4 4 2 2 3 2 2 2 2 1 4 1 2 2 3 3 1 1 4 2 2 3 1 3 1 3 2 2 1 3 4 1 2 3 3 1 1 1 2 3 1 3 4 4 4 2 4 3 2 2 3 4 4 1 3
[306] 1 2 3 3 3 3 4 1 1 3 2 3 2 4 1 2 1 4 1 1 2 2 4 3 3 1 1 3 3 4 2 3 4 2 1 3 4 2 3 3 1 2 1 4 2 3 2 1 2 3 3 1 4 2 1 2 2 1 2 3 1
[367] 4 1 3 1 2 2 1 3 1 1 2 3 1 4 3 3 1 1 3 1 1 3 4 3 4 4 3 3 4 1 2 1 3 2 4 3 1 2 4 4 4 1 3 2 3 2 2 3 3 3 2 4 4 4 3 3 2 3 3 2 1
[428] 3 3 1 2 2 3 2 2 3 4 3 3 4 2 3 4 3 1 2 2 3 3 3 4 2 3 3 3 1 4 3 4 3 2 2 4 4 3 4 2 2 1 3 4 2 1 2 3 2 1 4 1 3 2 2 4 4 3 2 2 4
[489] 3 3 4 3 3 4 3 2 4 4 1 3 4 4 1 1 2 2 4 4 4 4 4 2 4 2 3 2 3 3 4 3 2 4 4 3 4 3 4 2 2 3 3 2 4 3 4 2 1 4 1 4 2 1 1 1 4 1 4 4 3
[550] 4 2 4 1 4 1 1 1 3 2 4 1 3 1 3 3 4 1 2 3 2 1 1 3 4 2 2 3 4 4 1 3 3 2 4 4 4 2 1 2 2 2 4 1 1 1 2 3 1 2 1 3 1 3 4 2 4 4 3 3 4
[611] 2 1 2 2 3 2 2 1 4 4 4 4 4 3 2 3 4 2 4 1 2 1 3 1 2 3 1 2 4 3 1 4 3 4 2 3 3 3 2 3 4 2 4 2 3 3 1 2 1 2 3 4 3 2 2 3 4 1 4 3 2
[672] 1 2 3 4 3 1 1 1 2 2 3 3 3 3 2 2 3 1 1 4 4 3 3 1 1 4 1 1 4 3 1 3 1 2 1 2 2 2 1 3 3 3 1 3 2 1 4 1 1 3 3 1 4 2 2 3 4 4 3 4 2
[733] 4 1 3 2 1 1 4 2 2 3 3 4 1 2 3 1 2 2 2 1 2 2 2 4 1 2 1 2 3 3 4 2 1 1 3 2 3 2 2 4 1 4 1 4 4 1 1 1 3 2 4 1 2 4 2 2 2 2 3 4 4
[794] 4 1 4 2 1 3 3

我可以看到从 619 开始的值连续超过三个四,所以我的第一个 tibble 的真实类别必须是四个。

我创建了一个函数,然后是 运行 函数的 for 循环。该功能一次只处理一个小标题。它使用 lag() 函数回顾 3 行,如果所有值都匹配,它会在“重复”字段中捕获匹配的值。然后我过滤掉 1 到 4 以外的所有值,因为您似乎只对这些值感兴趣。然后我使用 summarize() 找到在“重复”字段中捕获的最大值并将其称为“class”。您似乎想使用字符串,所以我使用 case_when 将 class 值转换为字符串。该字符串是 returned 作为函数的结果。然后 for 循环循环遍历每个 tibbles 并在 results_list().

中捕获结果

在您的示例数据中,我没有看到任何值连续重复超过两次的小标题。我发现在所有小标题中,4 的值重复了两次,因此仅回顾一行的 运行 将 return 所有小标题的“四”的 class。我要么误解了你要找的东西,要么你的数据集不支持。

library(dplyr)

find_rep2 <- function(df){

    df1 <- df %>%
        mutate(repeat = ifelse(temp == lag(temp) & temp == lag(temp,2) & temp == lag(temp, 3), temp, NA)) %>%
        filter(temp %in% 1:4) %>%
        summarize(class = max(repeat, na.rm = TRUE)) 
    
    result <- case_when(
        df1$class == 4 ~ "four",
        df1$class == 3 ~ "three",
        df1$class == 2 ~ "two",
        df1$class == 1 ~ "one",
        TRUE ~ "undefined"
    )
}

results_list <- list()

for(i in 1:length(valueA)){
    df <- tibble(temp = valueA[[i]])
    results_list[[i]] <- find_rep2(df)
}

我终于找到了一个解决方案,尽管一点也不优雅。

valueA=replicate(50, tibble(floor(runif(800,min=1, max=5))))
valueB=list(list())
for (i in seq_along(valueA)){
  valueB[[i]]=rle(valueA[[i]]) 
}

cat=NA
for (i in seq_along(valueB)){
  for (j in seq(valueB[[i]][[1]])){
    if ((valueB[[i]]$values[j] == 4)&(valueB[[i]]$lengths[j] > 3)){
        cat[i] = 4
        break
    }
  }
}

for (i in seq_along(valueB)){
  for (j in seq(valueB[[i]][[1]])){
    if ((valueB[[i]]$values[j] == 3)&(valueB[[i]]$lengths[j] > 3)&(is.na(cat[i]))){
        cat[i] = 3
        break
    }
  }
}

for (i in seq_along(valueB)){
  for (j in seq(valueB[[i]][[1]])){
    if ((valueB[[i]]$values[j] == 2)&(valueB[[i]]$lengths[j] > 3)&(is.na(cat[i]))){
        cat[i] = 2
        break
    }
  }
}

for (i in seq_along(valueB)){
  for (j in seq(valueB[[i]][[1]])){
    if ((valueB[[i]]$values[j] == 1)&(valueB[[i]]$lengths[j] > 3)&(is.na(cat[i]))){
        cat[i] = 1
        break
    }
  }
}

我没有在 for 循环中使用 else if,而是使用了 4 个不同的 for 循环,在它们的 if 条件末尾添加了一个 break。 通过这样做,如果条件已经满足,我可以节省阅读整个循环的时间。 cat 值用 NA 填充,因此一旦检测到一个具有更高优先级的类别,将不会再次评估此 tibble。

我不得不使用最初发布的 rle() 函数。