Global meat production and consumption¶

We are going to analyze data from different sources to find answers to our key topics:

  • What is the the trend of meat production in terms of tonnes produced worldwide?
  • Who is accountable for the majority of produced and consumed meat (countries, regions,...)
  • How much meat is produced yearly and how many animals are slaugetered?
In [2]:
### Meat Production Data
In [3]:
import pandas as pd
import matplotlib.pyplot as plt 
import seaborn as sns
import numpy as np

# source: our world in data
global_meat_production = pd.read_csv('global-meat-production.csv')
global_meat_production.rename(columns={"Meat, total | 00001765 || Production | 005510 || tonnes": "Total Meat production (tonnes)"}, inplace=True)

print("Meat Production")
print(global_meat_production.head())
print("___________________________________")
print(global_meat_production.info())
Meat Production
        Entity Code  Year  Total Meat production (tonnes)
0  Afghanistan  AFG  1961                       129420.00
1  Afghanistan  AFG  1962                       132205.73
2  Afghanistan  AFG  1963                       138971.36
3  Afghanistan  AFG  1964                       143830.00
4  Afghanistan  AFG  1965                       150195.00
___________________________________
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 14382 entries, 0 to 14381
Data columns (total 4 columns):
 #   Column                          Non-Null Count  Dtype  
---  ------                          --------------  -----  
 0   Entity                          14382 non-null  object 
 1   Code                            11719 non-null  object 
 2   Year                            14382 non-null  int64  
 3   Total Meat production (tonnes)  14382 non-null  float64
dtypes: float64(1), int64(1), object(2)
memory usage: 449.6+ KB
None
In [4]:
# Drop duplicates
global_meat_production = global_meat_production.drop_duplicates()

Meat Consumption Data¶

In [5]:
meat_consumption_per_capita = pd.read_csv('meat-consumption-vs-gdp-per-capita.csv')

meat_consumption_per_capita.rename(columns={"Meat, total | 00002943 || Food available for consumption | 0645pc || kilograms per year per capita" : "Kilograms of Meat consumed per capita/year"}, inplace=True)

print("Meat Consumption")
print(meat_consumption_per_capita.head())
print("___________________________________")
print(meat_consumption_per_capita.info())
print("___________________________________")
Meat Consumption
        Entity      Code  Year  Kilograms of Meat consumed per capita/year  \
0     Abkhazia  OWID_ABK  2015                                         NaN   
1  Afghanistan       AFG  1961                                   14.719367   
2  Afghanistan       AFG  1962                                   14.738824   
3  Afghanistan       AFG  1963                                   15.176605   
4  Afghanistan       AFG  1964                                   15.378455   

   GDP per capita, PPP (constant 2017 international $) Continent  
0                                                NaN        Asia  
1                                                NaN         NaN  
2                                                NaN         NaN  
3                                                NaN         NaN  
4                                                NaN         NaN  
___________________________________
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 13866 entries, 0 to 13865
Data columns (total 6 columns):
 #   Column                                               Non-Null Count  Dtype  
---  ------                                               --------------  -----  
 0   Entity                                               13866 non-null  object 
 1   Code                                                 10978 non-null  object 
 2   Year                                                 13866 non-null  int64  
 3   Kilograms of Meat consumed per capita/year           12592 non-null  float64
 4   GDP per capita, PPP (constant 2017 international $)  6562 non-null   float64
 5   Continent                                            285 non-null    object 
dtypes: float64(2), int64(1), object(3)
memory usage: 650.1+ KB
None
___________________________________

Clean up Consumption Data¶

In [6]:
meat_consumption_per_capita = meat_consumption_per_capita[meat_consumption_per_capita['Year'] != 2022]

# Drop duplicates
meat_consumption_per_capita = meat_consumption_per_capita.drop_duplicates()

# Calculate median values for the relevant columns
median_meat_consumption = meat_consumption_per_capita['Kilograms of Meat consumed per capita/year'].median()
median_gdp_per_capita = meat_consumption_per_capita['GDP per capita, PPP (constant 2017 international $)'].median()

# Fill NaN values with the median values
meat_consumption_per_capita['Kilograms of Meat consumed per capita/year'] = meat_consumption_per_capita['Kilograms of Meat consumed per capita/year'].fillna(median_meat_consumption)
meat_consumption_per_capita['GDP per capita, PPP (constant 2017 international $)'] = meat_consumption_per_capita['GDP per capita, PPP (constant 2017 international $)'].fillna(median_gdp_per_capita)

# View the DataFrame to confirm NaN values are filled
print(meat_consumption_per_capita.info())
<class 'pandas.core.frame.DataFrame'>
Index: 13664 entries, 0 to 13864
Data columns (total 6 columns):
 #   Column                                               Non-Null Count  Dtype  
---  ------                                               --------------  -----  
 0   Entity                                               13664 non-null  object 
 1   Code                                                 10789 non-null  object 
 2   Year                                                 13664 non-null  int64  
 3   Kilograms of Meat consumed per capita/year           13664 non-null  float64
 4   GDP per capita, PPP (constant 2017 international $)  13664 non-null  float64
 5   Continent                                            285 non-null    object 
dtypes: float64(2), int64(1), object(3)
memory usage: 747.2+ KB
None

Production of meat: compare global trend vs. Western Europe and Germany¶

In [7]:
# World
production_global = global_meat_production[global_meat_production['Entity'] == 'World']

# Western Europe
production_western_europe = global_meat_production[global_meat_production['Entity'] == 'Western Europe (FAO)']

# Germany
production_germany = global_meat_production[global_meat_production['Entity'] == 'Germany']
In [8]:
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(18, 6))

axes[0].plot(production_global['Year'], production_global['Total Meat production (tonnes)'], label='Global')
axes[0].set_title('Global Meat Production Over Time')
axes[0].set_xlabel('Year')
axes[0].set_ylabel('Meat Production (tonnes)')
axes[0].legend(title='Region')
axes[0].grid(True)

axes[1].plot(production_western_europe['Year'], production_western_europe['Total Meat production (tonnes)'], label='Western Europe')
axes[1].set_title('Western Europe: Meat Production Over Time')
axes[1].set_xlabel('Year')
axes[1].set_ylabel('Meat Production (tonnes)')
axes[1].legend(title='Region')
axes[1].grid(True)

axes[2].plot(production_germany['Year'], production_germany['Total Meat production (tonnes)'], label='Germany')
axes[2].set_title('Germany: Meat Production Over Time')
axes[2].set_xlabel('Year')
axes[2].set_ylabel('Meat Production (tonnes)')
axes[2].legend(title='Region')
axes[2].grid(True)

# Adjust layout to prevent overlap
plt.tight_layout()

plt.show()

production_global.to_json('production_global.json', orient='records', lines=False)
production_western_europe.to_json('production_western_europe.json', orient='records', lines=False)
No description has been provided for this image

The short-term downturn in the popularity of meat production in the 90s is due to increasing health, ethical and sustainable awareness, but also to the outbreak of BSE. The subsequent increase is due to marketing strategies and new (to-go) products/snacks, globalization effects and thus increased availability.

But still, today in Germany and other Western countries, meat production is currently declining. This does not necessarily mean that the consumption is decreasing in the same rate since this trend could also be realted to an increase oof imported meat products.

Meat consumption worldwide per capita¶

In [9]:
# World
consumption_global = meat_consumption_per_capita[meat_consumption_per_capita['Entity'] == 'World']

# Western Europe
consumption_western_europe = meat_consumption_per_capita[meat_consumption_per_capita['Entity'] == 'Western Europe (FAO)']

# Germany
consumption_germany = meat_consumption_per_capita[meat_consumption_per_capita['Entity'] == 'Germany']

consumption_global.to_json('consumption_global.json', orient='records', lines=True)
In [10]:
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(18, 6))

axes[0].plot(consumption_global['Year'], consumption_global['Kilograms of Meat consumed per capita/year'], label='Global')
axes[0].set_title('Global Meat Consumption Over Time')
axes[0].set_xlabel('Year')
axes[0].set_ylabel('Meat Consumption (tonnes)')
axes[0].legend(title='Region')
axes[0].grid(True)

axes[1].plot(consumption_western_europe['Year'], consumption_western_europe['Kilograms of Meat consumed per capita/year'], label='Western Europe')
axes[1].set_title('Western Europe: Meat Consumption Over Time')
axes[1].set_xlabel('Year')
axes[1].set_ylabel('Meat Consumption (tonnes)')
axes[1].legend(title='Region')
axes[1].grid(True)

axes[2].plot(consumption_germany['Year'], consumption_germany['Kilograms of Meat consumed per capita/year'], label='Germany')
axes[2].set_title('Germany: Meat Consumption Over Time')
axes[2].set_xlabel('Year')
axes[2].set_ylabel('Meat Consumption (tonnes)')
axes[2].legend(title='Region')
axes[2].grid(True)

# Adjust layout to prevent overlap
plt.tight_layout()

plt.show()
No description has been provided for this image
In [22]:
# Filter the dataset for the year 2021
meat_consumption_2021 = meat_consumption_per_capita[meat_consumption_per_capita['Year'] == 2021]

# Define patterns or specific entities to exclude
patterns_to_exclude = [
    'FAO', 'WB', 'World', 'Africa', 'Asia', 'Europe', 'Americas', 
    'Oceania', 'Eastern', 'Western', 'Southern', 'Northern', 'Caribbean',
    'Union', 'Developing', 'Small Island', 'Low-income', 'High-income',
    'Upper-middle-income', 'Lower-middle-income', 'Arab', 'Central America',
    'South America', 'East Asia', 'Latin America'
]




# Filter out regions and non-country entities for 2021
meat_consumption_countries_only = meat_consumption_2021[~meat_consumption_2021['Entity'].str.contains('|'.join(patterns_to_exclude))]

# Filter out regions and non-country entities for all time
meat_consumption_countries_only_all_time = meat_consumption_per_capita[~meat_consumption_per_capita['Entity'].str.contains('|'.join(patterns_to_exclude))]


import seaborn as sns
import matplotlib.pyplot as plt

import seaborn as sns
import matplotlib.pyplot as plt

# Create scatterplot with a predefined Seaborn color palette
plt.figure(figsize=(10, 6))

sns.scatterplot(data=meat_consumption_countries_only, 
                x='GDP per capita, PPP (constant 2017 international $)', 
                y='Kilograms of Meat consumed per capita/year',
                hue='Entity',  # Example, assuming there's a 'Continent' column
                palette='Set2',   # Use a predefined Seaborn palette
                alpha=0.7,
                legend=False)  # Disable the legend

sns.regplot(data=meat_consumption_countries_only, 
            x='GDP per capita, PPP (constant 2017 international $)', 
            y='Kilograms of Meat consumed per capita/year',
            scatter=False, 
            color='red', 
            line_kws={"linewidth":2})

plt.show()

meat_consumption_countries_only.to_json('meat_consumption_countries_only.json', orient='records', lines=True)
No description has been provided for this image
In [23]:
plt.figure(figsize=(8, 6))
sns.boxplot(y='Kilograms of Meat consumed per capita/year', data=meat_consumption_countries_only_all_time)
plt.title('Boxplot of Meat Consumption for All Data')
plt.ylabel('Kilograms of Meat consumed per capita/year')
plt.show()
No description has been provided for this image

First conclusion¶

The relationship appears to have some degree of linearity. However, the data points are spread out, especially at higher GDP levels. The spread of the data and the presence of outliers or clusters at certain points can influence the linearity and the strength of the relationship.

There is a positive correlation between GDP per capita and meat consumption, but it’s not perfectly linear, as there are other factors at play. While there is a positive linear trend, the data shows some variability, and the relationship may not be perfectly linear.

Income Disparity in Consumption: The disparity in meat consumption is more pronounced at higher income levels, where some countries consume significantly more meat than others.

The spread of points at higher GDP levels also suggests greater variability in meat consumption. Some high-income countries have very high meat consumption, while others are lower, but still higher than in low-income countries.

It seems that countries increase their meat consumation when they "rise up". In the rich countries the consumation spreads more widely and seems to be dependent on other factors as well.

In [24]:
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score

# Assuming 'meat_consumption_countries_only' is already created and filtered for the year 2021 and other criteria
# Prepare the data for regression
X = meat_consumption_countries_only['GDP per capita, PPP (constant 2017 international $)'].values.reshape(-1, 1)
y = meat_consumption_countries_only['Kilograms of Meat consumed per capita/year'].values

# Fit the linear regression model
model = LinearRegression()
model.fit(X, y)

# Predict the values
y_pred = model.predict(X)

# Calculate the R-squared value
r_squared = r2_score(y, y_pred)

print(f'R-squared value: {r_squared}')
R-squared value: 0.25060315841352643

An R-squared of 0.251 indicates a moderate fit, meaning that while there is some relationship between GDP per capita and meat consumption, GDP alone does not fully explain the differences in meat consumption across countries.

Other factors, probably cultural factors, dietary preferences, regional influences or availability on markets come to play as well.

In [25]:
# Define the income groups of interest
income_groups = ['Low-income', 'High-income', 'Upper-middle-income', 'Lower-middle-income']

# Filter the dataset to include only the specified income groups
meat_consumption_income_groups = meat_consumption_2021[meat_consumption_2021['Entity'].str.contains('|'.join(income_groups))]

# Group the data by 'Entity' and calculate the mean meat consumption for each income group
meat_consumption_grouped = meat_consumption_income_groups.groupby('Entity')['Kilograms of Meat consumed per capita/year'].mean()
colors = ['#FF9999', '#66B2FF', '#99FF99', '#FFCC99']

# Create a bar plot
plt.figure(figsize=(10, 6))
meat_consumption_grouped.plot(kind='bar', color=colors)

# Adding titles and labels
plt.title('Meat Consumption per Capita by Income Group (2021)')
plt.xlabel('Income Group')
plt.ylabel('Kilograms of Meat consumed per capita/year')

# Show the plot
plt.show()

meat_consumption_grouped.to_json('meat_consumption_grouped.json', orient='records', lines=True)
No description has been provided for this image
In [26]:
# Filter the DataFrame for 'Upper-middle-income' and 'High-income'
upper_and_high_income = meat_consumption_2021[meat_consumption_2021['Entity'].str.contains('Upper-middle-income|High-income', regex=True)]
# Calculate the median meat consumption for the combined groups
median_combined_income = upper_and_high_income['Kilograms of Meat consumed per capita/year'].median()
print(f"Median Meat Consumption in 2021 for 'Upper-middle-income' and 'High-income': {median_combined_income} kg per capita")

lower_and_low_income = meat_consumption_2021[meat_consumption_2021['Entity'].str.contains('Low-income|Lower-middle-income', regex=True)]
# Calculate the median meat consumption for the combined groups
low_median_combined_income = lower_and_low_income['Kilograms of Meat consumed per capita/year'].median()
print(f"Median Meat Consumption in 2021 for low and lower income countries: {low_median_combined_income} kg per capita")

percentage_difference = ((median_combined_income - low_median_combined_income) / low_median_combined_income) * 100

print(f"Median Meat Consumption in 2021 for higher income countries compared to lower income countries is {round(percentage_difference)}%.")
Median Meat Consumption in 2021 for 'Upper-middle-income' and 'High-income': 76.153625 kg per capita
Median Meat Consumption in 2021 for low and lower income countries: 13.5609585 kg per capita
Median Meat Consumption in 2021 for higher income countries compared to lower income countries is 462%.
In [27]:
consumption_weurope = meat_consumption_2021[meat_consumption_2021['Entity'] == 'Western Europe (FAO)']
median_weurope = consumption_weurope['Kilograms of Meat consumed per capita/year'].median()
print(median_weurope)

consumption_weurope = meat_consumption_2021[meat_consumption_2021['Entity'] == 'Germany']
median_germany = consumption_weurope['Kilograms of Meat consumed per capita/year'].median()
print(median_germany)
77.59
76.58998
In [43]:
import geopandas as gpd
import matplotlib.pyplot as plt

# Use .loc[] to avoid the SettingWithCopyWarning
meat_consumption_countries_only.loc[
    meat_consumption_countries_only['Entity'] == 'United States', 'Entity'
] = 'United States of America'


# Load the world shapefile
world = gpd.read_file('ne_110m_admin_0_countries/ne_110m_admin_0_countries.shp')

# Merge the DataFrame with the world GeoDataFrame
merged = world.set_index('NAME').join(meat_consumption_countries_only.set_index('Entity'))

# Plotting the heatmap
fig, ax = plt.subplots(1, 1, figsize=(15, 10))
merged.plot(column='Kilograms of Meat consumed per capita/year', 
            cmap='OrRd', 
            linewidth=0.8, 
            ax=ax, 
            edgecolor='0.8', 
            legend=True)

ax.set_title('Meat Consumption Per Capita by Country (2021)', fontsize=15)
ax.set_axis_off()

plt.show()
No description has been provided for this image

Conclusion¶

Even if the GDP doesn't explain the variance in meat consumption we clearly can see that the amount of meat consumed is a question of wealth and income in these countries. Richer countries consume more than five times the amount of meat than lowe income countries - Whereas in the richer countries 76kg were consumed per capita, in the poorer countries it have been only 14kg.

In [ ]: