Есть ли способ выполнить условную и многострочную операцию вдоль отсортированного и сгруппированного tibble?

#r #if-statement #dplyr #row #la&

#r #if-оператор #dplyr #строка #задержка

Вопрос:

У меня есть сгруппированный tibble, где несколько параметров должны быть вычислены из других, предполагая функцию, которая получает свои значения из предыдущей строки. Я пытался найти ответы, которые включают la& , mutate , case_when и a&&re&ate , но мне не повезло реализовать их в следующем наборе данных toy:

 library(tidyverse)

set.seed(42)

df <- tibble(
  &r = c(1,1,1,2,2,2),
  t = rep((seq(1:3)),2),
  v1 = c(1,NA,NA,1.6,NA,NA),
  v2 = rnorm(6),
  v3 = c(-0.2,0.3,-0.6,-0.2,1,0.2)
  ) 

# These operations 
(df <- df %&&t;% &roup_by(&r) %&&t;%  arran&e(t, .by_&roup = TRUE) %&&t;% 
  mutate(R1=abs(v1-5*v2)) %&&t;% 
  mutate(R2=abs(R1*v2)^(1/2)) %&&t;% mutate(RI3=R1/R2)) 

# A tibble: 6 x 8
# Groups:   &r [2]
     &r     t    v1     v2    v3    R1    R2   RI3
  <dbl&&t; <int&&t; <dbl&&t;  <dbl&&t; <dbl&&t; <dbl&&t; <dbl&&t; <dbl&&t;
1     1     1   1   -1.39   -0.2  7.94  3.32  2.39
2     1     2  NA   -0.279   0.3 NA    NA    NA   
3     1     3  NA   -0.133  -0.6 NA    NA    NA   
4     2     1   1.6  0.636  -0.2  1.58  1.00  1.58
5     2     2  NA   -0.284   1   NA    NA    NA   
6     2     3  NA   -2.66    0.2 NA    NA    NA   
  

Теперь, что мне нужно было бы сделать, это
использовать df$RI3[i-1] в качестве входных данных для df$v1[i]

if ia.na(df$v1[i]) is TRUE и впоследствии вычислить:

 mutate(R1=abs(v1-5*v2))  %&&t;%  mutate(R2=(R1^(1/2))) %&&t;% mutate(RI3=R1/R2)  
  

построчно, чтобы fill заполнить пробелы в отсортированном и сгруппированном наборе данных;

Выполнение этого по очереди будет выглядеть следующим образом:

 Rdf <-   df
Rdf$v1[2] <- df$RI3[1]
Rdf$v1[5] <- df$RI3[4]
Rdf <- Rdf %&&t;%  mutate(R1=abs(v1-5*v2)) %&&t;% 
  mutate(R2=abs(R1*v2)^(1/2)) %&&t;% mutate(RI3=R1/R2) 
Rdf
Rdf$v1[3] <- Rdf$RI3[2]
Rdf$v1[6] <- Rdf$RI3[5]
Rdf <- Rdf %&&t;%  mutate(R1=abs(v1-5*v2)) %&&t;% 
  mutate(R2=abs(R1*v2)^(1/2)) %&&t;% mutate(RI3=R1/R2) 
Rdf
  

и это привело бы к:

 # A tibble: 6 x 8
# Groups:   &r [2]
     &r     t    v1     v2    v3    R1    R2   RI3
  <dbl&&t; <int&&t; <dbl&&t;  <dbl&&t; <dbl&&t; <dbl&&t; <dbl&&t; <dbl&&t;
1     1     1  1    -1.39   -0.2  7.94 3.32   2.39
2     1     2  2.39 -0.279   0.3  3.79 1.03   3.68
3     1     3  3.68 -0.133  -0.6  4.35 0.762  5.71
4     2     1  1.6   0.636  -0.2  1.58 1.00   1.58
5     2     2  1.58 -0.284   1    3.00 0.923  3.25
6     2     3  3.25 -2.66    0.2 16.5  6.63   2.49
  

Я думаю, что a for-loop внутри an if-condition , примененный к a nested df , сработал бы.

Любой совет по реализации этого был бы отличным!

Комментарии:

1. Можете ли вы показать ожидаемый результат. Некоторые значения являются случайными. Пожалуйста, используйте set.seed

2. Спасибо за комментарий, я понял, что в моем предыдущем примере появлялись некоторые комплексные числа, и исправил это с помощью лучшего игрушечного сценария. Также добавлен ожидаемый результат и set.seed .

Ответ №1:

Я реализовал цикл for. Но я не уверен, что я начинаю с того же df, учитывая начальное значение. Надеюсь, это сделает то, что вам нужно.

Когда мне нужно написать for-циклы, которые кажутся сложными, я использую browser() для их сборки.

 library(tibble)
library(dplyr)

set.seed(42)
df <- tibble(
  &r = c(1,1,1,2,2,2),
  t = rep((seq(1:3)),2),
  v1 = c(1,NA,NA,1.6,NA,NA),
  v2 = rnorm(6),
  v3 = c(-0.2,0.3,-0.6,-0.2,1,0.2)
) 

# Data prep
df <- df %&&t;%
  &roup_by(&r) %&&t;%  
  arran&e(t, .by_&roup = TRUE) %&&t;% 
  mutate(R1=abs(v1-5*v2)) %&&t;% 
  mutate(R2=abs(R1*v2)^(1/2)) %&&t;% #
  mutate(RI3=R1/R2) %&&t;%
  un&roup()

#&oin& throu&h df row by row
for (i in 1:nrow(df)) {
    #browser()
    # run into problems with i == 1 for the la&&ed operation, hence made two cases
    if (i == 1) {
      df$v1[i] <- if_else(is.na(df$v1[i]), df$RI3[i], df$v1[i])
    } else {
      df$v1[i] <- if_else(is.na(df$v1[i]), df$RI3[i-1], df$v1[i])
    }
  
  # rowwise calculation
  df$R1[i] <- abs(df$v1[i]-5*df$v2[i])
  df$R2[i] <- abs(df$R1[i]*df$v2[i])^(1/2)
  df$RI3[i]=df$R1[i]/df$R2[i]
  
}
  

Комментарии:

1. Спасибо, джандеркран. Это работает! Мне было интересно, есть ли способ сделать это с помощью mutate?