Объединение MIN и MAX в круговую функцию в R - PullRequest
2 голосов
/ 23 апреля 2020

У меня есть немного кода, который я использовал в электронной таблице Excel, которая использовала min и max, которую я пытаюсь перенести в R. У меня есть два столбца, "mini" и "maxi", которые представляют диапазон возможных значений. Третий столбец, который я пытаюсь заполнить, - это доля этого диапазона, которая находится между 5 и 19. Если посмотреть на первую строку в примере, если "mini" было 10, а "maxi" было 15, значение 5- 19 столбец должен быть 1, так как диапазон полностью попадает в этот диапазон. В строке 9 "mini" равно 1, а "maxi" равно 3, что означает, что оно полностью выходит за пределы диапазона 5-19 и, следовательно, должно быть 0. Строка 3, однако, перекрывает этот диапазон, и только 25% попадают в диапазон 5-19, поэтому выходное значение должно быть 0,25.

Вот пример того, как выглядит DF:

ID  mini maxi  
1   10  15
2   17  20
3   2   5
4   40  59
5   40  59
6   21  39
7   21  39
8   17  20
9   1   3
10  4   6

Код, который я использовал ранее, был примерно таким:

=MAX((MIN(maxi,19)-MAX(mini,5)+1),0)/(maxi-mini+1)

Сначала я пытался использовать что-то вроде

percentoutput <- mutate(DF, output = MAX((MIN(maxi,19) - MAX(mini,5) + 1),0)/(maxi-mini + 1))

Это привело к тому, что столбец ouput был заполнен NA. Я не был уверен, что в этой ситуации мне нужно запустить функцию apply, но я не уверен, как настроить go. Любое руководство приветствуется!

Вот пример DF:

structure(list(ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), min = c(10, 
17, 2, 40, 40, 21, 21, 17, 1, 4), max = c(15, 20, 5, 59, 59, 
39, 39, 20, 3, 6)), class = c("spec_tbl_df", "tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -10L), spec = structure(list(
    cols = list(ID = structure(list(), class = c("collector_double", 
    "collector")), mini = structure(list(), class = c("collector_double", 
    "collector")), maxi = structure(list(), class = c("collector_double", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

Ответы [ 3 ]

1 голос
/ 23 апреля 2020

Вот векторизованная версия с использованием data.table:

DT[, portion := {
    mn <- pmax(mini, lb)
    mx <- pmin(maxi, ub)
    fifelse(mn <= mx, (mx - mn + 1L) / (maxi - mini + 1L), 0)
}]

Или эквивалентно в базе R:

DF$mn <- pmax(DF$mini, lb)
DF$mx <- pmin(DF$maxi, ub)
DF$portion <- ifelse(DF$mn <= DF$mx, (DF$mx - DF$mn + 1L) / (DF$maxi - DF$mini + 1L), 0)

вывод:

    ID mini maxi   portion
 1:  1   10   15 1.0000000
 2:  2   17   20 0.7500000
 3:  3    2    5 0.2500000
 4:  4   40   59 0.0000000
 5:  5   40   59 0.0000000
 6:  6   21   39 0.0000000
 7:  7   21   39 0.0000000
 8:  8   17   20 0.7500000
 9:  9    1    3 0.0000000
10: 10    4    6 0.6666667

данные:

library(data.table)
DT <- fread("ID  mini maxi  
1   10  15
2   17  20
3   2   5
4   40  59
5   40  59
6   21  39
7   21  39
8   17  20
9   1   3
10  4   6")
lb <- 5L
ub <- 19L
1 голос
/ 24 апреля 2020

Мы можем использовать map2

library(dplyr)
library(purrr)  
df %>% 
      mutate(ratio = map2_dbl(min, max, ~ mean(.x:.y %in% 5:19)))
1 голос
/ 23 апреля 2020

Мы можем вычислить отношение значений min к max, которые находятся в диапазоне 5:19, используя rowwise.

library(dplyr)
df %>% rowwise() %>% mutate(ratio = mean(min:max %in% 5:19))

#      ID   min   max ratio
#   <dbl> <dbl> <dbl> <dbl>
# 1     1    10    15 1    
# 2     2    17    20 0.75 
# 3     3     2     5 0.25 
# 4     4    40    59 0    
# 5     5    40    59 0    
# 6     6    21    39 0    
# 7     7    21    39 0    
# 8     8    17    20 0.75 
# 9     9     1     3 0    
#10    10     4     6 0.667

и аналогично в базе R с использованием apply:

df$ratio <- apply(df[-1], 1, function(x) mean(x[1]:x[2] %in% 5:19))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...