1

I have a set of numbers / string that makes other number / string. I need to create a function that gives me a list of the all the numbers / string needed to create that number / string.

Consider the following dataset

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

If I input function(dog), I would like a list that returns bird and then cat. The function knows when to stop when ingredients = N/A (there's nothing more to look up).

It seems like some of sort of for loop that appends is the right approach.

needed <- list()

for (product in list){

  needed[[product]]<-df
}

df <- dplyr::bind_rows(product)
PDog
  • 143
  • 1
  • 2
  • 11

2 Answers2

0

I appended your initial code to make N/A simply equal to NA so I could use the is.na function in my R code. Now the sample data is

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

Code is below:

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)
}

I create an empty list and then create a while loop that just checks if the input exists in the product column. If so, it then checks to see if the corresponding ingredient to the product input is a non-NA value. If that's the case, the ingredient will be appended to ans and will become the new input. I also added a break statement to get out of the while loop when you reach an NA.

I did a quick test on the case where there is no NA in your dataframe and it appears to be working fine. Maybe someone else here can figure out a more concise way to write this, but it should work for you.

sumshyftw
  • 1,111
  • 6
  • 14
0

You can likely find a way to use a tree of some type to work through nodes. But, using a recursive function in base R, I have come up with this.

I have also changed the 'N/A' to NA to make life easier. Also, I have added in stringsAsFactors = F to the data frame.

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
}

This returns the input as well, which you can always drop off as the first element of the vector.

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