Обратный поиск цикла в R

#r #for-loop #reverse-lookup

#r #для цикла #обратный поиск

Вопрос:

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

Рассмотрим следующий набор данных

 ingredients <- c('N/A', 'cat', 'bird')
product <- c('cat', 'bird', 'dog')
data <- data.frame(ingredients, product)
head(data)
 

Если я введу функцию (dog), я хотел бы получить список, который возвращает bird, а затем cat. Функция знает, когда остановиться, когда ингредиенты = N / A (больше нечего искать).

Похоже, что какой-то цикл for, который добавляется, является правильным подходом.

 needed <- list()

for (product in list){

  needed[[product]]<-df
}

df <- dplyr::bind_rows(product)
 

Комментарии:

1. исправлено, потому что я тупой

Ответ №1:

Я добавил ваш исходный код, чтобы сделать N/A просто равным NA , чтобы я мог использовать is.na функцию в своем R-коде. Теперь образец данных

 ingredients <- c(NA, 'cat', 'bird')
product <- c('cat', 'bird', 'dog')
data <- data.frame(ingredients, product)
 

Код приведен ниже:

 ReverseLookup <- function (input) {
  ans <- list()
  while (input %in% data$product) {
    if (!is.na(as.character(data[which(data$product == input),]$ingredients))) {
      ans <- append(ans, as.character(data[which(data$product == input),]$ingredients))
      input <- as.character(data[which(data$product == input),]$ingredients)
    }
    else {
       break
     }
  }
  print(ans)
}

 

Я создаю пустой список, а затем создаю while цикл, который просто проверяет input , существует ли в product столбце. Если это так, затем он проверяет, является ли соответствующее ingredient product входному значению значение, отличное от NA. Если это так, то ingredient будет добавлено ans и станет новым input . Я также добавил break инструкцию для выхода из while цикла, когда вы достигнете NA .

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

Ответ №2:

Вероятно, вы можете найти способ использовать дерево некоторого типа для работы с узлами. Но, используя рекурсивную функцию в базе R, я придумал это.

Я также изменил ‘N / A’ на NA , чтобы упростить жизнь. Кроме того, я добавил в stringsAsFactors = F фрейм данных.

 ingredients <- c(NA, 'cat', 'bird')
product <- c('cat', 'bird', 'dog')
data <- data.frame(ingredients, product, stringsAsFactors = F)

reverse_lookup <- function(data, x, last_result = NULL) {
  if (! is.null(last_result)) {
    x <- data[data$product == last_result[length(last_result)], "ingredients"]
  }

  if (! is.na(x)) {
    last_result <- reverse_lookup(data, x, c(last_result, x))
  }

  last_result
}
 

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

 > reverse_lookup(data, "dog")
[1] "dog"  "bird" "cat"