
A cartoon panda is eating a banana. MidJourney 5
In 2023 The Economist published a way of talking about the climate cost of food that anyone can hold in their head. Instead of grams of COβ, express everything as bananas: how many times more carbon does a kilogram of this food emit than a kilogram of bananas?
They computed it three ways, because βa kilogram of lettuceβ and βa kilogram of beefβ are not the same amount of food. Per kilogram, per thousand calories, and per hundred grams of protein. The three rankings disagree, and the disagreement is the interesting part.
Tonight you rank this dataset three ways and work out what the disagreement means.
The Economist and Solstad, S., 2023. The Economistβs Banana index. First published in the article βA different way to measure the climate impact of foodβ, The Economist, April 11, 2023. The data are posted on GitHub.
Todayβs two sentences
Everything below is built from these. You should not need to look them up more than once.
df[df['column'] > value] # the filter sentence
df.sort_values('column', ascending=False).head(n) # the top-N sentenceSetup
Create a new notebook named
EOD_Day3_Banana_Index.ipynb.Add a title cell:
# Day 3 EOD: The Banana Index
Date: 09/02/2026Read the data, using
entityas the index. Theentitycolumn holds the food names, and making it the index means every ranking you print will be labelled with food names instead of row numbers.The file carries five columns that are bookkeeping rather than data:
year,Banana values,type,Chart?, andUnnamed: 16. Remove them.
.drop() takes a list of column names and axis='columns', and returns a new DataFrame without them. Here is the whole line. Run it as written:
df = df.drop(['year', 'Banana values', 'type', 'Chart?', 'Unnamed: 16'], axis='columns')Two things to notice. The names go in a list, exactly like the lists you used to select columns yesterday. And axis='columns' is what tells pandas you mean columns and not rows, because .drop() can remove either.
Part 1: Get your bearings
Start the way you started yesterday. Answer each in a markdown cell underneath the code.
- How many foods are in the dataset, and how many columns are left after the drop?
- Display the first few rows. What do the three columns whose names begin with
Bananas indexcontain? - Run
.info(). Two columns have missing values. Which, and how many? - What is the value of
Bananas index (kg)forBananasitself? Say why that number is what it is.
Part 2: Three rankings
Each of the three Bananas index columns is a ranking waiting to happen.
- Use the top-N sentence to display the 10 highest-scoring foods for
Bananas index (kg). - Do the same for
Bananas index (1000 kcalories). - Do the same for
Bananas index (100g protein).
Write each one out in full. Yes, that is the same sentence three times with one word changed. Notice how that feels.
You just wrote the same six words three times. Tomorrow morning youβll learn how to write it once, give it a name, and call it three times. Copying a line and changing one word in it is exactly the itch that functions exist to scratch, and it is worth having felt the itch before you get the cure.
- In a markdown cell, describe in two or three sentences how the three lists differ. Which foods are near the top of all three? Which appear on only one, and can you say why?
Part 3: Which foods are on every list?
Print the three top-10 lists again, one after another, and compare them by eye. Write down, in a markdown cell, the foods that appear in all three. There are three of them.
In a markdown cell: what does it mean for a food to be near the top of all three lists at once? What would it mean for a food to top one list and appear on neither of the others? Name one food of each kind.
Comparing three short lists by eye is the right tool for three short lists. Print them, read them, write down what you see. Automating a comparison this small costs more than it saves.
Part 4: Filtering by score
Now use the other sentence.
Use the filter sentence to find every food with a
Bananas index (kg)above 10. How many are there?Use
~to find the foods that are not above a score of 1 onBananas index (kg), that is, foods no worse than a banana by weight. How many are there?Now filter for
Bananas index (kg)below 1 instead. You get a different number. Explain the difference in one sentence.Use a two-condition filter to find the foods that score above 5 per kilogram and below 1 per 100 g of protein. End the line with
.copy(), since youβll display it a couple of ways. Display the two banana index columns for those foods, ranked byBananas index (kg).In a markdown cell: what do the foods in question 14 have in common? What is the argument this table makes about how we should compare foods?
Part 5: Land, not carbon
The banana index columns are all about emissions. The dataset also carries land use, in land_use_1000kcal: square metres of land per thousand calories.
Use
.loc[]to look up the value ofland_use_1000kcalforBananas.Use the top-N sentence to display the 10 foods with the highest
land_use_1000kcal.Use
.idxmax()onland_use_1000kcalto get the name of the single most land-hungry food. Then use two.loc[]lookups and a division to report how many times the bananaβs land use that food requires.Compare your land-use top 10 with your emissions top 10 from question 5. Are they the same foods? Answer in a markdown cell, and name one food that appears on one list and not the other.
Part 6: Cheese
The dataset has a lot of cheese in it. Cheese is worth a section of its own, because it is the one dairy product that shows up alongside meat at the top of the emissions rankings.
- Build a table of just the cheeses, then find the cheese with the highest
Bananas index (1000 kcalories).
The food names are the index of your table, not a column, so the filter sentence cannot reach them. .filter() can. Given a substring, it keeps every row whose label contains it:
cheese = df.filter(like='heese', axis='rows')like='heese' rather than 'cheese' so that Cheddar cheese and Cheesecake are both caught, whatever their capitalisation. Run the line as written, then rank cheese with the top-N sentence exactly as you have been doing all evening.
How many rows did
.filter(like='heese')give you? Look at the names carefully. Is every one of them a cheese? In a markdown cell, say what this tells you about matching on text.Where does the top cheese sit in the whole datasetβs calorie ranking? Check it against your answer to question 6.
Part 7: Write it up
In a single markdown cell of 200 to 300 words, answer this:
A friend tells you they are cutting bananas out of their diet for environmental reasons. Using this dataset, what would you tell them?
Your answer must cite at least three specific numbers you computed tonight, and must mention at least one place where the three rankings disagree with each other. Complete sentences, no bullet fragments.
The grammar minute
Look back through your notebook. Almost every code cell you wrote tonight was one of two sentences:
df[df['column'] > value] # filter: fewer rows
df.sort_values('column', ascending=False).head(n) # rank: same rows, new order, first fewEverything else was a variation. & and | joined two questions into one filter. ~ turned a question around. .idxmax() returned the label instead of the row. .loc[] looked up one value.
Two sentences, one evening, and you answered every question in this document. That is what a sentence pattern is for, and you will be writing both of these every day for the rest of the course.
Wrap-up
Before you close your notebook, check that:
- every claim in your Part 7 write-up has a code cell above it that produced the number
- you used the filter sentence and the top-N sentence at least three times each
- you can say out loud what
&needs that a single condition does not - your notebook reads top to bottom as a document, not as a pile of cells