【问题标题】:vector filling true or false based on the given conditions in R without cycle向量根据R中的给定条件填充真或假,没有循环
【发布时间】:2021-02-13 20:05:11
【问题描述】:

我有样本向量和一些值:

q = c(0.00000000, -0.70218526, -0.60635393,  0.32325554,  -0.45921704,  -0.57336113,  -0.77683717,
  -1.76347868,  -1.90884891,  -0.86157465,  -0.72896622,  -0.86831735,  -0.79357262,  -0.65279976,
  0.39921356,  0.78018094,  0.75703279,  0.70898895,  1.10155383,  0.88428135,  0.81338108,
  0.65611568,  0.89776945, 0.65447442,  0.16289673,  0.19464041,  0.01762445, -0.57663945,
  -1.01231868, -0.81204022, -0.99165533, -0.62666993, -1.05661282, -0.78221866, -0.03129549,  1.04051915)

s = -1.59688
i = -0.6373684
z = 0

我需要创建一个新的向量,其中将根据以下条件填充布尔值:

  • 如果 q 小于 i 我们填充 TRUE 直到
    • q 变得大于 0(即 z
    • 或直到 q 小于 s
  • 如果由于 s 值的条件而停止填充,则需要等待 q 大于 0 (即 z) 和
  • 之后才可以重新开始填写TRUE,否则填写FALSE

因此,对于这个示例数据,您应该得到以下结果(我手动填写):

out <- c(FALSE,  TRUE,  TRUE, FALSE, FALSE, FALSE,  TRUE, FALSE, FALSE, FALSE, FALSE,
                 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
                 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,  TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  TRUE, FALSE)

out

[1] FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

我想不使用循环,因为它们在 R 中太慢了

【问题讨论】:

  • @akrun 您能否更详细地描述需要澄清的内容
  • Aren't "直到q变得大于0(即z)才填充TRUE""等到q变得大于0(即, z) 并且只有在那之后你才能再次开始填充 TRUE” 矛盾吗?
  • 注意条件,我注意到我需要跳过填充TRUE,即使q没有达到零,只有在此之前q小于s

标签: r


【解决方案1】:

** 鉴于 OP 要求状态逻辑/策略的进一步编辑**

实际上,您的条件是三个条件的组合。如果我们创建四个区域,就像我在上图中创建的那样,并将这些区域命名为 1 到 4

  • 1 where q values are &gt;= z
  • 2 where q values are &gt;= i
  • 3 where q values are &gt;= s
  • 4 where q values are &lt; s

现在,条件可以翻译为

  • TRUE 在 2 区和 3 区时
  • 但是如果从这些TRUE区域退出一次,只有到达zone 3时才会变为TRUE
  • 此外,如果它已命中zone 4,则只有在它到达/命中zone 1 时,它才能变为TRUE,至少一次。

策略

  • 为了整合这些,我使用了 tidyverse 管道语法
    1. 首先将各个区域中的所有值相除(比如q1
    1. 作为第一个条件,在TRUE 中划分区域 2 和 3,在 `FALSE 中划分其他区域
    1. 作为第二个条件,比如c2,即是否从区域 4 退出并到达区域 1,将区域 4 标记为 F,将区域 1 标记为 T,其余全部为 NA。
    • 第一个值可以是NA,因此如果不适用,则将第一个值替换为 c1
    1. 作为最后一个条件说c3,即到达区域 3 时为 TRUE,将 3 标记为TRUE 1 和 4 标记为FALSE 并将区域 2 保留为NA 以便稍后检查它是否从哪个到达这里区。
    • 第一个值可以是NA,因此如果不适用,则将第一个值替换为FALSE
    • 现在只剩下工作来填补c2c3 的NA。使用 zoo::na.locftidyr::fill 填充所有 NA 将持续可用值。
    • 您最终想要的结果是所有条件的组合,所以c1 &amp; c2 &amp; c3
q = c(0.00000000, -0.70218526, -0.60635393,  0.32325554,  -0.45921704,  -0.57336113,  -0.77683717,
      -1.76347868,  -1.90884891,  -0.86157465,  -0.72896622,  -0.86831735,  -0.79357262,  -0.65279976,
      0.39921356,  0.78018094,  0.75703279,  0.70898895,  1.10155383,  0.88428135,  0.81338108,
      0.65611568,  0.89776945, 0.65447442,  0.16289673,  0.19464041,  0.01762445, -0.57663945,
      -1.01231868, -0.81204022, -0.99165533, -0.62666993, -1.05661282, -0.78221866, -0.03129549,  1.04051915)

s = -1.59688
i = -0.6373684
z = 0
library(tidyverse)
q %>% as.data.frame() %>% setNames('q') %>%
  mutate(q1 = case_when(q >= z ~ 1,
                        q >= i ~ 2,
                        q >= s ~ 3,
                        TRUE ~ 4),
         c1 = q1 %in% c(2,3),
         c2 = case_when(q1 == 4 ~ F,
                        q1 == 1 ~ T,
                        TRUE ~ NA),
         c2 = ifelse(row_number() == 1 & is.na(c2), c1, c2),
         c3 = case_when(q1 %in% c(1,4) ~ F,
                        q1 == 3 ~ T,
                        TRUE ~ NA),
         c3 = ifelse(row_number() ==1 & is.na(c3), F, c3)) %>%
  fill(c2, c3) %>%
  transmute(output = c1 & c2 & c3) %>% pull(output)
#>  [1] FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE
#> [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [25] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

reprex package (v2.0.0) 于 2021-06-02 创建


老答案

#data given
q = c(0.00000000, -0.70218526, -0.60635393,  0.32325554,  -0.45921704,  -0.57336113,  -0.77683717,
      -1.76347868,  -1.90884891,  -0.86157465,  -0.72896622,  -0.86831735,  -0.79357262,  -0.65279976,
      0.39921356,  0.78018094,  0.75703279,  0.70898895,  1.10155383,  0.88428135,  0.81338108,
      0.65611568,  0.89776945, 0.65447442,  0.16289673,  0.19464041,  0.01762445, -0.57663945,
      -1.01231868, -0.81204022, -0.99165533, -0.62666993, -1.05661282, -0.78221866, -0.03129549,  1.04051915)

s = -1.59688
i = -0.6373684
z = 0

#loading libraries
library(dplyr)
library(tidyr)

#creating zones
q1 <- dplyr::case_when(q >= z ~ 1,
                q >= i ~ 2,
                q >= s ~ 3,
                TRUE ~ 4)

#first condition
c1 <- dplyr::case_when(q1 %in% c(2,3) ~ T,
                TRUE ~ F)

#second condition (third in above statements)
c2 <- dplyr::case_when(q1 == 4 ~ F,
                q1 == 1 ~ T,
                TRUE ~ NA)

c2[1] <- ifelse(is.na(c2[1]), c1[1], c2[1])

c2 <- tidyr::fill(data.frame(id = 1:length(q), c2 = c2), c2)$c2

#third condition
c3 <- dplyr::case_when(q1 == 3 ~ T,
          q1 %in% c(1,4) ~ F,
          TRUE ~ NA)

c3[1] <- ifelse(is.na(c3[1]), F, c3[1])

c3 <- tidyr::fill(data.frame(id = 1:length(q), c3 = c3), c3)$c3

#creating output

output <- (c1 & c2 & c3)
> output
 [1] FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[21] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

#check it with your given `out`

> which((c1 & c2 & c3) == out)
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

#OR

> which((c1 & c2 & c3) != out)
integer(0)

更新如果您只想使用 baseR,请将这些表达式/代码用于 c2c3


#second condition
c2 <- case_when(q1 == 4 ~ F,
                q1 == 1 ~ T,
                TRUE ~ NA)

c2 <- c2[!cumsum(!is.na(c2)) | !is.na(c2)][cumsum(!cumsum(!is.na(c2)) | !is.na(c2))]

#third condition
c3 <- case_when(q1 == 3 ~ T,
          q1 %in% c(1,4) ~ F,
          TRUE ~ NA)

c3 <- c3[!cumsum(!is.na(c3)) | !is.na(c3)][cumsum(!cumsum(!is.na(c3)) | !is.na(c3))]

新数据

q <- c(-0.01563733, -0.05829460, -0.05884189, -0.08954093, -0.13268677, -0.31748724, -0.40060792, -0.08515156, -0.14303489, -0.24525535, -0.93842637, -0.77738228, -1.29502715, -0.89000932, -1.49038656, -1.64953167, -1.67114179, -1.47482366, -0.85874778, -1.01021450, -0.90078260, -1.24313333, -0.99053914, -1.11684140, -1.34073045, -1.36406163, -1.25163185, -1.42429376, -1.48127185, -1.79040671, -2.26811789, -1.82124304, -1.85208201, -1.76394637, -1.63173292) 
i = -0.489
s = -1.032
z = 0

#after running the above code
> output
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE
[17] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[33] FALSE FALSE FALSE

和图表

对于具有随机值的新向量

set.seed(202)
q <- runif(35, -2, 2)

【讨论】:

  • Q i = -0.489 , s = -1.032。不适用于新数据
  • 这不正确,第一个值,不是小于i,而是填充TRUE
  • 在一组新值上运行完美。立即尝试
猜你喜欢
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 1970-01-01
  • 2016-08-06
  • 2019-03-29
相关资源
最近更新 更多