Возвращаемое значение ifelse из другого вектора через индекс

Я не могу понять эту проблему относительно ifelse:

Скажем, у меня есть два вектора:

x <- c(0, 1:4, 1:4)
y <- letters[1:3]

Когда я делаю

ifelse(x==2, y[x], x)

я получил

"0" "1" "c" "3" "4" "1" "c" "3" "4"

Однако он должен вернуть "b" в позицию 2 вектора y. Почему ifelse это делает?

Не совсем уверен, что происходит с ifelse, но если вы всегда хотите 2-е место y, почему бы и нет ifelse(x == 2, y[2], x) ?

Ronak Shah 16.02.2019 15:00

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

gorg 16.02.2019 15:09

Он возвращает c, потому что: which(x==2) возвращает 3 and 7. Я не знаю, почему он не перерабатывает 7, а выбирает только 3. Возможно, потому, что длина y меньше 7.

NelsonGon 16.02.2019 15:18

y[x] возвращает это: "a" "b" "c" NA "a" "b" "c" NA, я полагаю, что с 0 в качестве индекса R преобразует x из числового в множитель, а возврат 2 становится третий элемент. Я не могу найти никаких документов, подтверждающих эту теорию.

Dave2e 16.02.2019 15:41

Однако это не фактор, это вектор символов (проверено на результат).

Elin 16.02.2019 16:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
212
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Из комментария: Он возвращает c, потому что: which(x==2) возвращает 3 и 7. Я не знаю, почему он не перерабатывает 7, а выбирает только 3. Возможно, потому что y меньше длины 7

Пытаться:

ind<-which(x==2)
ind1<-ind[1]-1
ifelse(x==2,y[ind1],x)
[1] "0" "1" "b" "3" "4" "1" "b" "3" "4"

Вот попытка сделать функцию:

dynamic_index<-function(ind,x,y){
  x<-x
  y<-y
  ind1<-which(x==ind)
 ind2<-ind1[1]-1
  ifelse(x==ind,y[ind2],x)
}
dynamic_index(2,x,y)

Вы используете 0 в качестве индекса в первом элементе, поэтому выравнивание испорчено.

y[x]

[1] "a" "b" "c" NA  "a" "b" "c" NA

Так

> y[0]
character(0)
> y[1]
[1] "a"
> y[2]
[1] "b"
> y[3]
[1] "c"

Таким образом, длина y[x] отличается от длины x.

То, что вы хотите, это

> ifelse(x==2, y[x+1], x)
[1] "0" "1" "c" "3" "4" "1" "c" "3" "4"

но только если первый элемент всегда равен 0.

Старый ответ Так как

x <- c(0, 1:4, 1:4)

возвращается

[1] 0 1 2 3 4 1 2 3 4

так x==2 возвращается

1] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE

так для y = letters[1:3]

ifelse(x==2, y[x], x)

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

В документации для ifelse говорится, что если один вектор слишком короткий, он будет переработан, что вы и ожидаете. c("a","b","c","a","b","c","a").

Однако, когда я пытаюсь

ifelse(x==3, y[x], x)

я получил

[1] "0" "1" "2" NA  "4" "1" "2" NA  "4"

Что говорит мне о том, что переработка работает не так, как я ожидал.
Так что это номинальная причина, по которой вы получаете результат. Причина, по которой это работает, - это то, чего я сейчас не знаю, но если я выясню это, я добавлю к этому ответу. Я подозреваю, что это связано с преобразованием в строку.

Просто глядя на y[x] я понимаю

[1] "a" "b" "c" NA  "a" "b" "c" NA

Что, кстати, имеет длину всего 8, хотя x имеет длину 9.

Так что на самом деле это вообще не имеет отношения к ifelse(), это действительно другая проблема с переработкой.

Ответ принят как подходящий

Для объяснения этого странного поведения полезен исходный код ifelse (см. ниже).

Как только вы вызываете ifelse, выражения, переданные в качестве аргументов test, yes и no, оцениваются, что приводит к:

Browse[2]> test
[1] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE
Browse[2]> yes
[1] "a" "b" "c" NA  "a" "b" "c" NA 
Browse[2]> no
[1] 0 1 2 3 4 1 2 3 4

Обратите внимание, что y[x] использует значения x для выбора значений из y. и значение 0 пусто (= игнорируется), значения выше 3 - нет данных, вот почему аргумент «да» становится

[1] "a" "b" "c" NA "a" "b" "c" NA

Строка кода

ans[test & ok] <- rep(yes, length.out = length(ans))[test & ok]

затем применяется в конце и эффективно обновляет все TRUE-элементы, используя логический вектор test:

yes[test]

что приводит к:

[1] "c" "c"

хранится в результирующих индексах 3 и 7

ans[test & ok]

Таким образом, проблема заключается в использовании y[x] в качестве второго аргумента для ifelse + неинтуитивное поведение ifelse для использования логического индекса для выбора «ИСТИННЫХ» результатов из y[x]...

Извлеченный урок: избегайте сложной логики ifelse, она имеет много побочных эффектов (например, вы можете потерять правильный тип данных или атрибуты).

# ifelse function
function (test, yes, no) 
{
  if (is.atomic(test)) {
    if (typeof(test) != "logical") 
      storage.mode(test) <- "logical"
    if (length(test) == 1 && is.null(attributes(test))) {
      if (is.na(test)) 
        return(NA)
      else if (test) {
        if (length(yes) == 1) {
          yat <- attributes(yes)
          if (is.null(yat) || (is.function(yes) && identical(names(yat), 
                                                             "srcref"))) 
            return(yes)
        }
      }
      else if (length(no) == 1) {
        nat <- attributes(no)
        if (is.null(nat) || (is.function(no) && identical(names(nat), 
                                                          "srcref"))) 
          return(no)
      }
    }
  }
  else test <- if (isS4(test)) 
    methods::as(test, "logical")
  else as.logical(test)
  ans <- test
  ok <- !(nas <- is.na(test))
  if (any(test[ok])) 
    ans[test & ok] <- rep(yes, length.out = length(ans))[test & 
                                                           ok]
  if (any(!test[ok])) 
    ans[!test & ok] <- rep(no, length.out = length(ans))[!test & 
                                                           ok]
  ans[nas] <- NA
  ans
}

Ваше использование выражения x[y], вероятно, следует исправить на y[x]

IRTFM 16.02.2019 17:19

Результат получается латентным, потому что функция == возвращает вектор логики:

x <- c(0, 1:4, 1:4)
y <- letters[1:3]

ifelse(x==2, y[x], x)

#look at x==2
x==2
[1] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE

Это логический вектор, который имеет true в третьей позиции, а не во второй, поэтому выбирается третье значение y. Это также показывает, почему ответ, который ссылается на поведение which, неверен.

Почему же поведение which некорректно? Мы видим, что x==2 имеет значение TRUE дважды, то есть в позициях 3 и 7.

NelsonGon 16.02.2019 15:44

Ответ which неверен, потому что исходный код ifelse не использует which, но ИМХО косвенно верен, потому что логический вектор все равно выбирает значения этих индексов ;-)

R Yoda 16.02.2019 15:46

Ах, да, но это все тот же результат, независимо от того, какой код использует ifelse (по моему скромному и менее опытному мнению). which — это просто вспомогательная функция (imhleo)

NelsonGon 16.02.2019 15:47

Это было утверждение «Я не знаю, почему он не перерабатывает 7», которое заставило меня подумать, что использование которого привело к определенному недоумению.

IRTFM 16.02.2019 17:14

х <- с(0, 1:4, 1:4) у <- буквы [1:3]

если иначе (х == 2, у [х], х)

в ifelse он проверит каждую позицию в x. Если это правда, то он напечатает позицию y[x], это означает, что позиция, которая была проверена в x, и эта позиция значения в Y будет напечатана. он проверит все значения в Икс

Другие вопросы по теме