Разница в значениях между разными столбцами, удовлетворяющими заданному условию - PullRequest
0 голосов
/ 13 ноября 2018

Вот мои данные игрушки. У меня есть переменные val и квартили от q0 до q4.

 df <- tibble::tribble(
      ~val, ~q0, ~q1, ~q2,  ~q3, ~q4, ~q, ~diff,
       15L, 15L, 15L, 15L,   15, 15L, 4L,     0,
       17L,  2L, 16L, 30L,   34, 54L, 2L,    13,
       29L,  2L, 16L, 30L,   34, 54L, 2L,     1,
       25L,  2L, 17L, 20L,   26, 43L, 3L,     1 )

Мне нужно вычислить две последние переменные так, чтобы:

  1. Когда val находится между q1 и q2, я выбираю 2 (из q2) для переменной q (2nd строка)
  2. Если есть ничья, я выбираю максимум qs (например, q = 4 в 1-м ряду)
  3. diff - это разница между q и val. Так, для строки 1 это q4-val = 0, а для строки 2 это q2 - val = 30 - 17 = 13.

Как я могу вычислить q и diff в R, предпочтительно используя tidyverse? Может быть, мы можем использовать ответы здесь: Извлечь имя столбца и конкретное значение на основе условия .

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Когда у вас есть более сложная логика, подобная этой, я считаю, что обычно лучше обернуть ее в функцию. В будущем будет легче поддерживать, читать и отлаживать. Я также был бы очень осторожен при использовании большого количества вложенных ifelse-операторов или больших case_when. В принятом ответе q может быть только 2, 3 или 4. Не предусмотрено ни одного случая, чтобы q было равно 1, что вам, безусловно, нужно в качестве опции в вашем конечном продукте.

df <- tibble::tribble(
~val, ~q0, ~q1, ~q2,  ~q3, ~q4, ~q, ~diff,
15L, 15L, 15L, 15L,   15, 15L, 4L,     0,
17L,  2L, 16L, 30L,   34, 54L, 2L,    13,
29L,  2L, 16L, 30L,   34, 54L, 2L,     1,
25L,  2L, 17L, 20L,   26, 43L, 3L,     1 )

whichQ <- function(df, qs = c('q0', 'q1', 'q2', 'q3', 'q4')) {
    # This has the flexibility of changing your column names / using more or less Q splits
    qDf <- df[, qs]
    # This finds the right quantile by finding how many you are larger than
    # It works because the q's are sequential
    whichGreater <- df$val >= qDf
    q <- apply(whichGreater, 1, sum)
    # 4 is a special case because there is no next quantile
    q <- ifelse(q == 5, 4, q)
    df$q <- q
    # Go through the Qs we found and grab the value of that column
    diff <- sapply(seq_along(q), function(x) {
        as.integer(qDf[x, q[x]+1])
    })
    # Get the difference
    df$diff <- diff - df$val
    df
}

Вы все еще можете использовать это с трубопроводом, но это более ясно (я думаю), что происходит, если вы называете свою функцию чем-то полезным.

df %>% 
    whichQ %>% 
    head(2)
0 голосов
/ 13 ноября 2018

Попробуйте:

library(tidyverse)
df <- tribble(
        ~val, ~q0, ~q1, ~q2,  ~q3, ~q4,
        15L, 15L, 15L, 15L,   15, 15L,
        17L,  2L, 16L, 30L,   34, 54L,
        29L,  2L, 16L, 30L,   34, 54L,
        25L,  2L, 17L, 20L,   26, 43L)

df %>%
        mutate(q = ifelse(val > q1 & val < q2, 2,
                          ifelse(val == q0 & val == q1 & val == q2 & val == q3 & val == q4, 4,
                                 3)),
               diff = ifelse(val > q1 & val < q2, q2 - val,
                             ifelse(val == q0 & val == q1 & val == q2 & val == q3 & val == q4, q4 - val,
                                    q3 - val)))
# A tibble: 4 x 8
    val    q0    q1    q2    q3    q4     q  diff
  <int> <int> <int> <int> <dbl> <int> <dbl> <dbl>
1    15    15    15    15    15    15     4     0
2    17     2    16    30    34    54     2    13
3    29     2    16    30    34    54     2     1
4    25     2    17    20    26    43     3     1

С case_when (при условии, что когда val находится между q2 и q3, вы выбираете 3).

df %>%
        mutate(q = case_when(val > q1 & val < q2  ~ 2,
                             val == q0 & val == q1 & val == q2 & val == q3 & val == q4 ~ 4,
                             val > q2 & val < q3 ~ 3),
               diff = case_when(val > q1 & val < q2 ~ q2 - val,
                                val == q0 & val == q1 & val == q2 & val == q3 & val == q4 ~ q4 - val,
                                val > q2 & val < q3 ~ as.integer(q3 - val)))
# A tibble: 4 x 8
    val    q0    q1    q2    q3    q4     q  diff
  <int> <int> <int> <int> <dbl> <int> <dbl> <int>
1    15    15    15    15    15    15     4     0
2    17     2    16    30    34    54     2    13
3    29     2    16    30    34    54     2     1
4    25     2    17    20    26    43     3     1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...