Обратный поиск для цикла в R - PullRequest
1 голос
/ 15 апреля 2019

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

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

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

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

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

needed <- list()

for (product in list){

  needed[[product]]<-df
}

df <- dplyr::bind_rows(product)

Ответы [ 2 ]

0 голосов
/ 15 апреля 2019

Вероятно, вы можете найти способ использовать дерево какого-либо типа для работы через узлы. Но, используя рекурсивную функцию в базе 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"
0 голосов
/ 15 апреля 2019

Я добавил ваш исходный код, чтобы сделать 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, ипохоже, работает нормально.Может быть, кто-то еще здесь может найти более краткий способ написать это, но это должно работать для вас.

...