如何在 r 中使用 if 条件基于其他列创建新列

How to create a new column based on other columns with if conditions in r

无法找到基于列中事件组的 if 条件生成新列的方法。

名为 "BF" 的列代表流列的 (i-3),并且对于每个 "event" 组将是相同的 BF。例如,在第5行中,"BF"的值为39,这是事件列中所有“2”的流列(第2行的流)的前第三个值。 问题是 BF[i] 不能大于 flow[i]。如果 BF[i] 大于 flow[i],则 BF 应该是流的 (i-4) 或 (i-5) 或 (1-6)... 直到 BF[i] 等于或小于 flow[i]。例如,在第 10 行中,"BF" 列的值大于 "flow" 列的值,因此,第 10 行中 BF_1(我要创建的列)的值是 37,表示最接近的 flow 的较低值,在本例中是 flow[i-6].

例如,我们有以下数据框:

flow<- c(40, 39, 38, 37, 50, 49, 46, 44, 43, 45, 40, 30, 80, 75, 50, 55, 53, 51, 49, 100)
event<- c(1,1,1,1,2,2,2,2,2,3,3,3,4,4,4,5,5,5,5,6)
BF<- c(NA, NA, NA, NA, 39, 39, 39, 39, 39, 46, 46, 46, 45, 45, 45, 80, 80, 80, 80, 53)
a<- data.frame(flow, event, BF)

这就是我正在寻找的愿望输出。我想创建 BF_1 列。

   flow event BF  BF_1
1    40   1   NA   NA
2    39   1   NA   NA
3    38   1   NA   NA
4    37   1   NA   NA
5    50   2   39   39
6    49   2   39   39
7    46   2   39   39
8    44   2   39   39
9    43   2   39   39
10   45   3   46   37
11   40   3   46   37
12   30   3   46   37
13   80   4   45   45
14   75   4   45   45
15   50   4   45   45
16   55   5   80   30
17   53   5   80   30
18   51   5   80   30
19   49   5   80   30
20  100   6   53   53

是否有可能生成列 BF_1?请让我知道任何想法。我正在使用 for 循环并使用 if 条件,但我无法保留整个事件列组的 BF 值。

编码效率有点低,可以使用 dplyr 等..,但它会完成工作并匹配给定的 BF_1

flow <- c(40, 39, 38, 37, 50, 49, 46, 44, 43, 45, 40, 30, 80, 75, 50, 55, 53, 51, 49, 100)
event <- c(1,1,1,1,2,2,2,2,2,3,3,3,4,4,4,5,5,5,5,6)
BF <- c(NA, NA, NA, NA, 39, 39, 39, 39, 39, 46, 46, 46, 45, 45, 45, 80, 80, 80, 80, 53)
a <- data.frame(flow, event, BF)

a$BF_1 <- NA #default to NA first

for(i in 1:length(unique(a$event))){

  if(is.na(a[a$event == i, "BF"][1])) next

  if(a[a$event == i, "BF"][1] < a[a$event == i, "flow"][1]) a[a$event == i, "BF_1"] <- a[a$event == i, "BF"][1]

  if(a[a$event == i, "BF"][1] > a[a$event == i, "flow"][1]) {
    head <- min(which(a$event==i))-6 
    if (min(head-6) < 0) head <- 1 #making sure it doesn't overflow to row 0
    a[a$event == i, "BF_1"] <- min( a[  head:min(which(a$event==i)), "flow"] ) #fill the min of the subset flow column given position
  }

}

a

一个 tidyverse 可能性是:

a %>%
 left_join(crossing(a, a) %>%
            filter(event > event1) %>%
            group_by(event) %>%
            filter(flow == first(flow)) %>%
            slice(1:(n() - 3)) %>%
            slice(which.max(cumsum(flow > flow1))) %>%
            ungroup() %>%
            transmute(event,
                      flow_flag = flow1), by = c("event" = "event")) %>%
 mutate(BF_1 = ifelse(lag(flow, 3) > flow, flow_flag, lag(flow, 3))) %>%
 group_by(event) %>%
 mutate(BF_1 = first(BF_1)) %>%
 select(-flow_flag)

    flow event    BF  BF_1
   <dbl> <dbl> <dbl> <dbl>
 1    40     1    NA    NA
 2    39     1    NA    NA
 3    38     1    NA    NA
 4    37     1    NA    NA
 5    50     2    39    39
 6    49     2    39    39
 7    46     2    39    39
 8    44     2    39    39
 9    43     2    39    39
10    45     3    46    37
11    40     3    46    37
12    30     3    46    37
13    80     4    45    45
14    75     4    45    45
15    50     4    45    45
16    55     5    80    30
17    53     5    80    30
18    51     5    80    30
19    49     5    80    30
20   100     6    53    53

它可能过于复杂,但它所做的是首先创建值的所有组合(因为所需值理论上可以在数据中的任何位置)。其次,它确定每组满足条件的第一个案例(不考虑之前的第三个值)。最后,它将它与原始 df 结合起来,如果每组的前 3 个值满足条件,则 returns 它,否则 returns 值首先满足条件小于实际值。