I'm trying to ease my life by writing a menu creator, which is supposed to permutate a weekly menu from a list of my favourite dishes, in order to get a little bit more variety in my life.
I gave every dish a value of how many days it approximately lasts and tried to arrange the dishes to end up with menus worth 7 days of food.
I've already tried solutions for knapsack functions from here, including dynamic programming, but I'm not experienced enough to get the hang of it. This is because all of these solutions are targeting only the most efficient option and not every combination, which fills the Knapsack.
library(adagio)
#create some data
dish <-c('Schnitzel','Burger','Steak','Salad','Falafel','Salmon','Mashed potatoes','MacnCheese','Hot Dogs')
days_the_food_lasts <- c(2,2,1,1,3,1,2,2,4)
price_of_the_food <- c(20,20,40,10,15,18,10,15,15)
data <- data.frame(dish,days_the_food_lasts,price_of_the_food)
#give each dish a distinct id
data$rownumber <- (1:nrow(data))
#set limit for how many days should be covered with the dishes
food_needed_for_days <- 7
#knapsack function of the adagio library as an example, but all other solutions I found to the knapsackproblem were the same
most_exspensive_food <- knapsack(days_the_food_lasts,price_of_the_food,food_needed_for_days)
data[data$rownumber %in% most_exspensive_food$indices, ]
#output
dish days_the_food_lasts price_of_the_food rownumber
1 Schnitzel 2 20 1
2 Burger 2 20 2
3 Steak 1 40 3
4 Salad 1 10 4
6 Salmon 1 18 6
Simplified:
I need a solution to a single objective single Knapsack problem, which returns all possible combinations of dishes which add up to 7 days of food.
Thank you very much in advance
I am having trouble finding a way to cleaning update the amount column in table 1 with the price column in table 2. I know that left_join and merge could be used to join the price column, rename it, and then drop it, but I am wondering if there is simpler way to avoid creating a mess.
I should state that the real dataset is more complicated and that the amount column in table 1 needs to be conditionally updated somehow based on table 2.
Table 1
Fruit
Vegetable
amount
apple
broccoli
pear
spinach
pineapple
carrot
Table 2
Fruit
Vegetable
price
apple
broccoli
10
pear
spinach
5
pineapple
carrot
2
If you don't want to use merge and update process you can use match.
table1$amount <- table2$price[match(paste(table1$Fruit, table1$Vegetable),
paste(table2$Fruit, table2$Vegetable))]
I have been trying to read a CSV into R. The CSV is separated in a strange way with all values within one column separated by commas like in this picture. The top row is the column names and then below are the values
When I try read_csv("filename") nothing shows up in the tibble except a bunch of NA values like in this picture after running the view function . How can I approach this?
Here is the data for reference
, Calories, Fat (g), Carb. (g), Fiber (g), Protein (g)
Chonga Bagel,300,5,50,3,12
8-Grain Roll,380,6,70,7,10
Almond Croissant,410,22,45,3,10
Apple Fritter,460,23,56,2,7
Banana Nut Bread,420,22,52,2,6
Blueberry Muffin with Yogurt and Honey,380,16,53,1,6
Blueberry Scone,420,17,61,2,5
Butter Croissant,240,12,28,1,5
Butterfly Cookie,350,22,38,0,2
Cheese Danish,320,16,36,1,8
Chewy Chocolate Cookie,170,5,30,2,2
Chocolate Chip Cookie,310,15,42,2,4
Chocolate Chunk Muffin,440,21,60,2,7
Chocolate Croissant,330,18,38,1,6
Chocolate Hazelnut Croissant,390,22,43,2,7
Chocolate Marble Loaf Cake,490,24,64,2,6
Cinnamon Morning Bun,390,15,56,2,8
Cinnamon Raisin Bagel,270,1,58,3,9
Classic Coffee Cake,390,16,57,1,5
Cookie Butter Bar,360,23,36,0,2
Use the following code to read the data
df = read.csv("starbucks-menu-nutrition-food.csv", skipNul = T)
head(df, 2)
ÿþ Calories Fat..g. Carb...g. Fiber..g. Protein..g.
1 Chonga Bagel 300 5 50 3 12
2 8-Grain Roll 380 6 70 7 10
Then you may consider renaming the columns like for e.g.
colnames(df) <- c("Food", "Calories", "Fat", "Carb", "Fiber", "Protein")
for further processing of the data.
In R, I need to remove rows with multiple combinations from 2 character columns. I have searched for a solution, but most questions either deal with duplicates, or are only trying to remove 1 combination, not multiple combinations based on two columns. Here is an example df:
Species Harvest Hunt.Type
Sheep 1 Gun
Goat 4 Bow
Turkey 3 Gun
Pig 2 Bow
Quail 6 Bow
Here, I would need to remove any row that has a mammal species with "Gun" in the Hunt.Type, and any row that has a bird species with a "Bow" Hunt.Type. So I would want to end up with this:
Species Harvest Hunt.Type
Goat 4 Bow
Turkey 3 Gun
Pig 2 Bow
My data frame is much larger than this with 13 species and many more columns and rows.
I tried to do this using extract on conditions in base r as well as dplyr but I could not figure it out because of the added complication of the multiple combinations of species.
I tried something like this in base r:
df[df$Species== c("Goat" , "Sheep", "Pig") &
df$Hunt.Type == "Gun",]
But for some reason that code omits some rows with those conditions, and keeps others. for dplyr, I have not been able to get anything even close.
Yes, I would suggest to create a vector of all birds or mammals (whichever is shorter) and then filter. We need only one of them since the other half are just their complements. So assuming if a Species is not bird then it's a mammal and vice versa.
So for this example, we can do
bird.keywords <- c("Turkey", "Quail")
df[!with(df, (Species %in% bird.keywords & Hunt.Type == "Bow") |
(!Species %in% bird.keywords) & Hunt.Type == "Gun"),]
# Species Harvest Hunt.Type
#2 Goat 4 Bow
#3 Turkey 3 Gun
#4 Pig 2 Bow
Silly example df, "cat":
species color tail_length
calico brown 6
calico gray 6
tabby multi 5
tabby brown 5
Suppose I want to create a new variable, personality. The values here will be recoded based on tail_length, but will also be conditional upon the species and color of the cat. So the ideal final df would look like this:
species color tail_length personality
calico brown 6 mean
calico gray 6 nice
tabby multi 5 mean
tabby brown 5 nice
At present, I'm using the codes:
library(car)
cat$personality<-recode(cat$tail_length, "'6'==mean, '5'==nice")
cat$personality[cat$species=="calico" & cat$color=="brown"] <- mean
cat$personality[cat$species=="calico" & cat$color=="gray"] <- nice
cat$personality[cat$species=="tabby" & cat$color=="multi"]<- mean
cat$personality[cat$species=="tabby" & cat$color=="brown"]<-nice
My main question is this: is there a simpler way to do this/consolidate these functions into one?
Given that I made up this example data on the fly, please take it with a grain of salt when answering.
Thanks! As an R beginner, I really appreciate your help.
Here's one approach using qdap and qdapTools (CRAN packages that I maintain):
library(qdap); library(qdapTools)
key <- list(
mean = c( "calico.gray", "tabby.brown"),
nice = c("calico.brown", "tabby.multi")
)
dat[["personality"]] <- paste2(dat[1:2]) %l% key
dat
## species color tail_length personality
## 1 calico brown 6 nice
## 2 calico gray 6 mean
## 3 tabby multi 5 nice
## 4 tabby brown 5 mean
Basically you create a key that's a named list based on the combined columns. Then %l% acts as a hash table lookup.
There isn't much you can do here because, at the end of the day, you still need to specify the conditions and new variables to assign.
However, you can cut down on the boilerplate code by using within:
within(cat, {
personality <- recode(tail_length, "'6'==mean, '5'==nice")
personality[species == "calico" & color == "brown"] <- "mean"
personality[species=="calico" & color=="gray"] <- "nice"
personality[species=="tabby" & color=="multi"] <- "mean"
personality[species=="tabby" & color=="brown"] <- "nice"
})
This is really just a merge operation. (Furthermore, you have over specified the criteria since species and tail_length are completely dependent. But since it's only an example that may not be an issue.) Let's say your first dataframe is dat and the criteria dataframe is lookup. Then all you need to do is:
> merge(dat, lookup)
species color tail_length personality
1 calico brown 6 mean
2 calico gray 6 nice
3 tabby brown 5 nice
4 tabby multi 5 mean
Not a very interesting or dramatic result because it looks just like the lookup dataframe, but give it something a bit larger and:
> merge( rbind(dat,dat,dat) , lookup)
species color tail_length personality
1 calico brown 6 mean
2 calico brown 6 mean
3 calico brown 6 mean
4 calico gray 6 nice
5 calico gray 6 nice
6 calico gray 6 nice
7 tabby brown 5 nice
8 tabby brown 5 nice
9 tabby brown 5 nice
10 tabby multi 5 mean
11 tabby multi 5 mean
12 tabby multi 5 mean