Вложенный оператор ifelse в цикле for - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь использовать вложенный оператор ifelse в цикле for для создания новой переменной, значения которой основаны на частоте появления факторной переменной (список почтовых индексов).

Новая переменная должна возвращать предопределенную серию чисел, основанную на частоте почтового индекса (диапазон частот от 1 до 4). Каждый из этих числовых рядов должен заканчиваться на 800 и увеличиваться с шагом 200, начальная точка которого зависит от частоты каждого почтового индекса: чем выше частота, тем ниже начальный прирост на 200.

Для этого я определил цикл for, в котором я сначала измеряю частоту каждого почтового индекса, а затем вложенный оператор ifelse, определяя каждую серию чисел, которые должны быть выделены NewVar на основе частоты.

Небольшой интуитивно понятный пример того, чего я хочу достичь, написан здесь, я хочу применить это к кадру данных, содержащему миллионы почтовых индексов.

желаемый результат:

Postcode  NewVar
AA        600
AA        800
BB        400
BB        600
BB        800
CC        800
DD        200
DD        400
DD        600
DD        800

КОД:

DF$NewVar <- 0

DF$NewVar <- for (i in levels(DF$Postcode[i]))
ifelse((table(DF$Postcode[i]) == 4), DF$NewVar[i] <- c(200,400,600,800),
  (ifelse ((table(DF$Postcode[i]) == 3), DF$NewVar[i] <- c(400,600,800),
    (ifelse ((table(DF$Postcode[i]) == 2), DF$NewVar[i] <- c(600,800), 
      DF$NewVar[i] <- c(800))))))

ЗАДАЧА 1:

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

Error in `$<-.data.frame`(`*tmp*`, NewVar, value = c("0", "0", "0",  : 
replacement has 11 rows, data has 10.

ПРОБЛЕМА 2:

ИСПЫТАНИЕ, ЕСЛИ ЛИБО РАБОТАЕТ НА СВОЙ СОБСТВЕННОСТИ (ИЗ ПЕТЛИ):

При проверке, работает ли предложение ifelse само по себе (вне цикла), я вижу, что на каждую строку NewVar копируется только начальный шаг, равный 200, поэтому он не увеличивается до 800. Это не то, что я хотите достичь либо:

КОД ПРОВЕРКИ ОДНОГО IFELSE:

DF$NewVar[1:2] <- ifelse((sum(table(DF$Postcode)) == 2),                       
  DF$NewVar[1:2] <- c(600,800), "NA")

РЕЗУЛЬТАТ (не желательно):

Postcode  NewVar
AA        200
AA        200

желаемый результат:

Postcode  NewVar
AA        200
AA        400

Примечание. Я предварительно определил столбец NewVar, прежде чем пытаться выделить переменную, и уже проверил наличие NA.

Заранее благодарим вас за ваше время.

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Для полноты, вот базовое решение R, в котором используется функция ave().

Предположим, Postcode - это вектор почтовых индексов в случайном порядке:

Postcode
 [1] "BB" "CC" "CC" "BB" "BB" "AA" "CC" "BB" "AA" "DD"

код ниже создает data.frame, включающий Postcode и NewVar:

data.frame(
  Postcode, 
  NewVar = ave(Postcode, Postcode, 
               FUN = function(x) seq(to = 800, by = 200, length.out = length(x)))
)
   Postcode NewVar
1        BB    200
2        CC    400
3        CC    600
4        BB    400
5        BB    600
6        AA    600
7        CC    800
8        BB    800
9        AA    800
10       DD    800

Данные

# create data
library(magrittr)   # only used to improve readability
n_codes <- 4L
set.seed(1L)
Postcode <- 
  stringr::str_dup(LETTERS[1:n_codes], 2L) %>% # create codes
  rep(times = sample(n_codes)) %>%             # replicate randomly
  sample()                                     # re-order randomly
0 голосов
/ 10 января 2019

В одну сторону, если вы хотите использовать dplyr :

library(dplyr)
DF <- structure(list(Postcode = c("AA", "AA", "BB", "BB", "BB", "CC", 
"DD", "DD", "DD", "DD")), class = "data.frame", row.names = c(NA, 
-10L))

vals <- c(200,400,600,800)
DF %>% group_by(Postcode) %>% mutate(NewVar = tail(vals,n()))
...