Проблемы с порядком при использовании mutate с условием ifelse на сегодняшний день - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь использовать mutate для создания столбца, который принимает значение одного столбца до точки, а затем использует cumprod для заполнения остальных наблюдений на основе значений другого столбца.

Я попытался объединить mutate с ifelse, но порядок утверждений неверен, и я не могу понять, почему

Ниже я приведу более простой пример, который повторяет мою проблему:

foo1 <- data.frame(date=seq(2005,2018,1))
foo1 %>% mutate(h=ifelse(date>2008, seq(1,11,1), 99))

Вывод:

   date  h
1  2005 99
2  2006 99
3  2007 99
4  2008 99
5  2009  5
6  2010  6
7  2011  7
8  2012  8
9  2013  9
10 2014 10
11 2015  1
12 2016  2
13 2017  3
14 2018  4

И мне бы хотелось, чтобы это было:

   date  h
1  2005 99
2  2006 99
3  2007 99
4  2008 99
5  2009  1
6  2010  2
7  2011  3
8  2012  4
9  2013  5
10 2014  6
11 2015  7
12 2016  8
13 2017  9
14 2018 10

Редактировать:

Ниже я воспроизвожу другой пример(ближе к тому, что я пытаюсь сделать).

foo2 <- data.frame(date=seq(2005,2013,1), a=seq(1, by=1, length.out = 9), b=rep(1.01, length.out = 9))
foo2 %>% mutate(h=ifelse(date>2008, cumprod(c(a[5],b[5:9])), a))

Вывод, который у меня есть:

  date a    b       h
1 2005 1 1.01 1.00000
2 2006 2 1.01 2.00000
3 2007 3 1.01 3.00000
4 2008 4 1.01 4.00000
5 2009 5 1.01 5.20302
6 2010 6 1.01 5.25505
7 2011 7 1.01 5.00000
8 2012 8 1.01 5.05000
9 2013 9 1.01 5.10050

И я бы хотел, чтобы это было:

  date a    b       h
1 2005 1 1.01 1.00000
2 2006 2 1.01 2.00000
3 2007 3 1.01 3.00000
4 2008 4 1.01 4.00000
5 2009 5 1.01 5.00000
6 2010 6 1.01 5.05000
7 2011 7 1.01 5.10050
8 2012 8 1.01 5.20302
9 2013 9 1.01 5.25505

Если я использую if_else вместо ifelse, я получаю следующую ошибку:

Error in mutate_impl(.data, dots) : 
  Evaluation error: `true` must be length 9 (length of `condition`) or one, not 6

Ответы [ 2 ]

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

Функция ifelse принимает три аргумента:

  1. test: вектор logical.Скажем, что он имеет длину N.
  2. yes: вектор.Это может быть любой длины.Если длина не N, вектор перерабатывается / сокращается до длины N
  3. no: то же, что и yes.

В концеэтой стадии предварительной обработки у вас есть 3 одинаковых вектора длины.ifelse затем строит возвращаемое значение, выбирая второй или третий вектор в зависимости от test.

В вашем случае мы имеем:

test <- foo1$date>2008 #length: 14
yes <- seq(1,11,1) #length: 11
no <- 99 #length: 1

Итак, необходимо перезапустить обаyes и no.Вы получите что-то вроде:

 test yes no
FALSE   1 99
FALSE   2 99
FALSE   3 99
FALSE   4 99
 TRUE   5 99
 TRUE   6 99
 TRUE   7 99
 TRUE   8 99
 TRUE   9 99
 TRUE  10 99
 TRUE  11 99
 TRUE   1 99
 TRUE   2 99
 TRUE   3 99

Вы увидите, как работает корзина.Затем для построения возвращаемого значения ifelse выбирает в указанном порядке элементы yes, если test равно TRUE и no элементы в противном случае.Это объясняет, почему у вас есть это возвращаемое значение.Это не о dplyr конечно.

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

Вы были почти там:

foo1 %>% mutate(h = if_else(date > 2008, cumsum(date > 2008), 99L))
#   date  h
#1  2005 99
#2  2006 99
#3  2007 99
#4  2008 99
#5  2009  1
#6  2010  2
#7  2011  3
#8  2012  4
#9  2013  5
#10 2014  6
#11 2015  7
#12 2016  8
#13 2017  9
#14 2018 10

PS.Рекомендуется использовать if_else вместо базовых R ifelse.

...