#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"