如何检测条件何时连续发生 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() 函数。
我已经创建了下一个可重现的最小示例来模拟我的问题。
我有一个 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() 函数。