Округлить до следующего значимого числа

Я работаю над функцией построения графика, и мне нужно определить, где размещать метки осей. При вычислении приращений между каждой меткой я хочу избежать меток со значениями 142, 284 и т. д., а предпочел бы их со значениями 150, 300 и т. д.

Однако цифры не всегда находятся в одном диапазоне. Вот как я планирую округлить их с помощью функции:

  1. от 0 до 1: округлить до первого десятичного знака
  2. от 1 до 10: округлить до целого числа или 0,5
  3. от 11 до 20: округлить до целого числа
  4. от 21 до 100: округлить до числа, кратного 5
  5. от 101 до 200: округлить до числа, кратного 10
  6. от 201 до 1000: округлить до числа, кратного 50
  7. между 1001 и 2000: округлить до числа, кратного 100
  8. между 2001 и 10000: округлить до числа, кратного 500

Моя проблема заключается в числе 2. Как округлить до числа, кратного 0,5? Кроме того, существует ли альтернативная стандартная функция, которую можно использовать для таких проблем с маркировкой?


person bumblebee    schedule 04.11.2019    source источник
comment
Возможный дубликат stackoverflow.com/questions /8664976/r-раунд-к-ближайшим-5-или-1   -  person Ronak Shah    schedule 04.11.2019
comment
Чтобы округлить до числа, кратного 0,5, вы можете умножить на 2, округлить до полного целого числа, а затем разделить на 2.   -  person Henry    schedule 04.11.2019


Ответы (1)


Я бы предложил использовать case_when dplyr для создания такого набора правил.

library(dplyr)
my_format <- function(x) {
  case_when(
    between(x, 0,     1)     ~ ceiling(x / .1 ) * .1,
    between(x, 1,     10)    ~ ceiling(x / .5 ) * .5,
    between(x, 11,    20)    ~ ceiling(x / 1  ) * 1,
    between(x, 21,    100)   ~ ceiling(x / 5  ) * 5,
    between(x, 101,   200)   ~ ceiling(x / 10 ) * 10,
    between(x, 201,   1000)  ~ ceiling(x / 50 ) * 50,
    between(x, 1001,  2000)  ~ ceiling(x / 100) * 100,
    between(x, 2001,  10000) ~ ceiling(x / 500) * 500
  )
}

my_format(0.44)
#> [1] 0.5
my_format(4.1)
#> [1] 4.5
my_format(4.51)
#> [1] 5
my_format(11.1)
#> [1] 12
my_format(22.5)
#> [1] 25
my_format(121.1)
#> [1] 130
my_format(201.1)
#> [1] 250
my_format(1002.3)
#> [1] 1100
my_format(2001.1)
#> [1] 2500
person JBGruber    schedule 04.11.2019
comment
Может работать для текущей проблемы, а теперь представьте, что это округление доходит до миллиардов. - person zx8754; 04.11.2019
comment
Я не вижу, чтобы это было заявлено как возможность в вопросе. Но да, тогда это не сработает, и нужно будет найти более общую функцию. - person JBGruber; 04.11.2019
comment
Но любой, кто может предоставить более общую форму, может опубликовать! - person JBGruber; 04.11.2019