и кепка это в 5:

я есть фрейм данных с именем «преступления», который содержит столбец «pre_rate», который обозначает уровень преступности до того, как определенный закон будет реализован. Я хотел бы поместить каждую ставку в столбец "rate_category", используя вложенный цикл if-else. У меня есть следующий код:

crimes$rate_category = 
  with(crimes, ifelse(pre_rate > 0.26 && pre_rate < 0.87, 1,
    ifelse(pre_rate > 1.04 && pre_rate < 1.94, 2, 
      ifelse(pre_rate > 2.03 && pre_rate < 2.96, 3, 
        ifelse(pre_rate > 3.10 && pre_rate < 3.82, 4, 
          ifelse(pre_rate > 4.20 && pre_rate < 11.00, 5, "NA"))))))
crimes

и вот воспроизводимый пример:

pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80) 
crimes = data.frame(pre_rate)   
crimes

Однако, когда я запускаю цикл с моим исходным фреймом данных, все уровни в столбце «rate_category» неправильно устанавливаются на 1. В чем проблема с циклом выше?

 Hugh04 дек. 2017 г., 04:45
Это действительно ваша цель, чтобы иметь пробелы? Например, хотите ли вы, чтобы предварительная ставка 2 была NA?
 Marius04 дек. 2017 г., 01:23
Будьте осторожны с использованием&&: он сравнивает только первый элемент векторов.& делает поэлементное сравнение, что, вероятно, то, что вы хотели.
 Marius04 дек. 2017 г., 01:25
Также я думаю, что с характером"NA" в вашем финалеifelse испортит столбец, преобразовав его в символ. Просто используйтеNA, без кавычек.
 Jin Yu Li04 дек. 2017 г., 05:04
@ Да, все ставки равны 8 десятичным, поэтому я просто округляю их до сотых. Будут пробелы, но они не будут содержать соответствующих данных.

Ответы на вопрос(5)

а затем полагаться на индексацию? Используя этот метод, нет необходимости писатьpre_rate > num1 & pre_rate < num2 много раз.

lowB <- c(0.26, 1.04, 2.03, 3.10, 4.2)
uppB <- c(0.87, 1.94, 2.96, 3.82, 11)

myCategory <- 1:5 ## this can be whatever categories you'd like

crimes$rate_category <- with(crimes, myCategory[pre_rate > lowB & pre_rate < uppB])

и вы просто хотите индекс, вы можете использовать.bincode:

crimes$rate_category <- .bincode(crimes$pre_rate,
                                 breaks = c(-Inf, 1, 2, 3, 4, Inf))

Если вам нужны конкретные значения для каждого интервала, вы можете использовать скользящее соединение черезdata.table пакет:

library(magrittr)
library(data.table)

rate_category_by_pre_rate <- 
  data.table(rate_category = c("foo", "bar", "foobar", "baz", "foobie"),
             pre_rate = c(1, 2, 3, 4, 11)) %>%
  setkey(pre_rate)

crimes %>%
  as.data.table %>%
  setkey(pre_rate) %>%
  rate_category_by_pre_rate[., roll = -Inf]

#>    rate_category pre_rate
#> 1:           foo     0.27
#> 2:           bar     1.91
#> 3:        foobar     2.81
#> 4:           baz     3.21
#> 5:        foobie     4.80

Однако в вашем случае вам может понадобиться толькоceiling (то есть округлить значениеpre_rate и кепка это в 5:

crimes$rate_category <- pmin(ceiling(crimes$pre_rate), 5)

#>   pre_rate rate_category
#> 1     0.27             1
#> 2     1.91             2
#> 3     2.81             3
#> 4     3.21             4
#> 5     4.80             5

Вместо нескольких вложенныхifelse(),неравное соединение а такжеобновление при присоединении может быть использован

# OP's sample data set with one out-of-bounds value appended
crimes = data.frame(pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80, 1.0))   

library(data.table)
# specify categories, lower, and upper bounds
bounds <- data.table(
  cat = 1:5,
  lower = c(0.26, 1.04, 2.03, 3.10, 4.2),
  upper = c(0.87, 1.94, 2.96, 3.82, 11)
)
# non-equi join and update on join
setDT(crimes)[bounds, on = .(pre_rate > lower, pre_rate < upper), rate_category := cat][]
   pre_rate rate_category
1:     0.27             1
2:     1.91             2
3:     2.81             3
4:     3.21             4
5:     4.80             5
6:     1.00            NA

Обратите внимание, чтоpre-rate значения, которые находятся за пределами любого из заданных интервалов, получаютNA rate_category автоматически.

ы, он должен быть быстрее, чем ваш ifelse:

pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80) 
crimes = data.frame(pre_rate)   
crimes$rate = (pre_rate > 0.26 & pre_rate < 0.87)*1 + 
  (pre_rate > 1.04 & pre_rate < 1.94)* 2 + 
  (pre_rate > 2.03 & pre_rate < 2.96)* 3 + 
  (pre_rate > 3.10 & pre_rate < 3.82)* 4 + 
  (pre_rate > 4.20 & pre_rate < 11.00)* 5

Идея здесь состоит в том, чтобы просто получить истинные или ложные значения из выражения, тогда оно умножается на число, для которого вы видите это как категорию. Единственная разница будет в том, что вы не получите здесь NA для несоответствия, вместо этого вы получите ноль, который вы, конечно, можете изменить. Также для добавления используйте «&» в тех случаях, когда вы хотите векторизовать (соответствие элемента элементу) свой результат, как упомянуто в комментариях.

Выход:

#> crimes
# pre_rate rate
#1     0.27    1
#2     1.91    2
#3     2.81    3
#4     3.21    4
#5     4.80    5
 Hugh04 дек. 2017 г., 06:30
Вы также можете включить только< отношения и опустить коэффициенты для строго возрастающего кодирования.

Вместо вложения ifelse я мог бы рекомендовать использоватьcase_when, Это немного легче читать / следовать. Но, как сказал @Marius, ваша проблема заключается в&& Вместо того, чтобы использовать&.

library(tidyverse)
crimes <- data.frame(pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80))

crimes %>% 
  mutate(rate_category = case_when(pre_rate > 0.26 & pre_rate < 0.87 ~ 1,
                                   pre_rate > 1.04 & pre_rate < 1.94 ~ 2,
                                   pre_rate > 2.03 & pre_rate < 2.96 ~ 3,
                                   pre_rate > 3.10 & pre_rate < 3.82 ~ 4,
                                   pre_rate > 4.20 & pre_rate < 11.00 ~ 5))
 Hugh04 дек. 2017 г., 04:44
Между () может быть полезно здесь.
 Hugh04 дек. 2017 г., 12:40
Верный. Однако из комментария ФП кажется вероятным, что это различие не имеет значения.
 Uwe04 дек. 2017 г., 12:31
@ Хью Согласно странице справки,?dplyr::between это ярлык дляx >= left & x <= right но ОП проситстрогий неравенства.data.table реализацияbetween() имеет параметр для обеспечения строгих неравенств, например,data.table::between(x, lower, upper, incbounds = FALSE).

Ваш ответ на вопрос