This vignette will guide you through the livestock-related data available within the Evidence for Resilient Agriculture (ERA) dataset. The dataset serves as a critical resource for understanding agricultural resilience, specifically focusing on livestock systems and their adaptation to climate change.

We will cover the following:

Methodology:

1. Search Terms Used

2. Screening Criteria Applied

3. Data Extraction Process

Exploration of Livestock Data in ERA:

1. Exploring geographic locations of studies available

2. Practices in changing diets

3. Understanding Diet compositions

4. Common outcomes reported

Methodology

ERA Search Terms

Our initial search, conducted in 2014, queried the Web of Science and Scopus Databases for English language articles. Database queries consisted of key terms describing three components: technology, outcome, and geographic location. Given the myriad outcomes of interest, we constructed distinct search strings for each category: productivity, resilience, and mitigation outcomes, as well as a key term related to barriers to adoption.

Our methodology employed Boolean operators ‘OR’ and ‘AND’ to ensure the comprehensiveness of the search. This string for each technology category was run in both search engines for each of the outcome categories, ‘productivity,’ ‘resilience,’ ‘mitigation,’ and additionally for ‘barriers’.

Below in a snippet of the search terms used for the livestock extraction:

Search Terms for ERA Livestock
Source Subject Query
WoS Livestock (Livestock OR ‘mono gastric’ OR cattle OR sheep OR goats OR pigs OR poultry OR ruminant OR aquaculture OR fish) AND (‘non-conventional feed’ OR ‘Forage productivity’ OR grass OR ‘pasture additive’ OR ‘grass-legume’ OR ‘feed conversion’ OR ‘feed intake’ OR ‘protein intake’ OR ‘energy intake’ OR ‘feed availability’ OR ‘feed supplement’ OR ’energy retention’ OR ’growth rate’ OR ’feed acceptability’ OR ’feeding frequency’ OR ’stover digestibility’ OR ’paddock’ OR ’freerange’ OR ‘hay’ OR ‘silage’ OR ‘fodder shrub’ OR ’nomadic’ OR pastoral OR ’signalgrass’ OR (pasture NEAR cerrado) OR ‘crop residue’ OR ‘animal husbandry’ OR ‘pasture species’ OR ‘crop-pasture’ OR ‘pasture crop’ OR ’zero graz’ OR ‘rotational graz’ OR ’conti graz’ OR ’stocking density’ OR ’organic livestock’ OR ‘ammonia volatil’ OR ’N-retention’ OR ’cover manure’ OR ‘biogas capture’ OR ‘Manure acidification’ OR ‘Cover* manure’ OR ‘Manure collection’ OR ‘manure treatment’ OR ‘artificial insemination’ OR ‘trait selection’ OR ‘heat period’ OR ovulation OR hybrid OR ‘desirable traits’ OR ‘progeny test’ OR ‘semen analysis’ OR ‘cross breed’ OR ’Aquasilviculture’ OR ’Integrated multi-trophic aquaculture’ OR ’Organic Aquaculture’ OR ’fishing intensity’ OR ’culture based fishery’ OR ’vulnerable’ OR ’susceptible’ OR ’resistan’ OR ‘quarantine’ OR ‘antibiotic’ OR ‘vaccine’ OR ‘dewormer’ OR ‘ectoparasite’ OR ‘innoculation’ OR ’agropasto’ OR (Livestock AND (antistress OR ‘anti-stress’)))
Scopus Livestock (Livestock OR ‘mono gastric’ OR cattle OR sheep OR goats OR pigs OR poultry OR ruminant OR aquaculture OR fish) AND (‘non-conventional feed’ OR ‘Forage productivity’ OR grass OR ‘pasture additive’ OR ‘grass-legume’ OR ‘feed conversion’ OR ‘feed intake’ OR ‘protein intake’ OR ‘energy intake’ OR ‘feed availability’ OR ‘feed supplement’ OR ’energy retention’ OR ’growth rate’ OR ’feed acceptability’ OR ’feeding frequency’ OR ’stover digestibility’ OR ’paddock’ OR ’freerange’ OR ‘hay’ OR ‘silage’ OR ‘fodder shrub’ OR ’nomadic’ OR pastoral OR ’signalgrass’ OR (pasture W/ cerrado) OR ‘crop residue’ OR ‘animal husbandry’ OR ‘pasture species’ OR ‘crop-pasture’ OR ‘pasture crop’ OR ’zero graz’ OR ‘rotational graz’ OR ’conti graz’ OR ’stocking density’ OR ’organic livestock’ OR ‘ammonia volatil’ OR ’N-retention’ OR ’cover manure’ OR ‘biogas capture’ OR ‘Manure acidification’ OR ‘Cover* manure’ OR ‘Manure collection’ OR ‘manure treatment’ OR ‘artificial insemination’ OR ‘trait selection’ OR ‘heat period’ OR ovulation OR hybrid OR ‘desirable traits’ OR ‘progeny test’ OR ‘semen analysis’ OR ‘cross breed’ OR ’Aquasilviculture’ OR ’Integrated multi-trophic aquaculture’ OR ’Organic Aquaculture’ OR ’fishing intensity’ OR ’culture based fishery’ OR ’vulnerable’ OR ’susceptible’ OR ’resistan’ OR ‘quarantine’ OR ‘antibiotic’ OR ‘vaccine’ OR ‘dewormer’ OR ‘ectoparasite’ OR ‘innoculation’ OR ’agropasto’ OR (Livestock AND (antistress OR ‘anti-stress’)))

Screening Criteria with PICOS Standards

This screening criteria is designed to systematically review papers focusing on livestock management and outcomes, applying both inclusion and exclusion criteria based on specific parameters. The framework ensures that the selected studies align with the objectives of the review, particularly within the context of livestock systems in Africa.

PICOS Framework The PICOS framework helps structure systematic reviews by defining key components: Population, Intervention, Comparison, Outcomes, and Study Design.

Population (P):

The criteria focus on studies involving livestock, excluding fish unless explicitly directed (fish are separated into a distinct category). The geographic scope is limited to studies conducted in Africa.

Intervention (I):

Eligible studies involve practices like: Pasture and grazing management. Feed experiments (including feed processing). Improved variety and herd density management. Manure management and related practices.

Comparison (C):

Studies should ideally have a control group, except for papers reporting diet and intake where controls are not mandatory.

Outcomes (O):

The review emphasizes studies reporting primary data on key outcomes: Reproductive performance, economics, yields, soil quality, biodiversity, emissions, and labour. Studies that report surveys or specific emission-related outcomes in controlled environments are included, but consultation with the team is recommended.

Study Design (S):

Studies must focus on interventions and primary data collection. Lab experiments or greenhouse studies are excluded unless they focus on emission outcomes.

Data Extraction Process

Data were extracted from tables, text, and figures. Figures were digitized using available software, such as Web Plot Digitizer (https://apps.automeris.io/wpd/).

The data was extracted using a macros enabled excel template:

https://cgiar-my.sharepoint.com/:x:/g/personal/p_steward_cgiar_org/EXUFiZJ-jopBoxHaC9MsBHUBHC-qVT66csvmjvxluJ_CWQ?e=bEG8kY

There are 9 sections to this workbook:
1) Pub = Publication: capture bibliographic data about an experiment here.
2) Site & Site Soils: captures information about experimental sites, any detailed information about soil variables should be captured in Site.Soils
3) ExpD = Experimental design, captures information about the number of study replicates, plot sizes, etc.
4) Practices= These include the following:

-Time periods

-Breed: Capturing information on whether the breed used in the experiment is improved or indegenous.

-Diets: This is broken into 3 tables; Ingredients fed to the animals, Nutritional content of each ingredient and the digestibility of those ingredients.

-Chemicals, Vaccines, Medicines that were given to the animals during the experiment

Image 1: Data extraction table for ingredients fed to the animals
Image 1: Data extraction table for ingredients fed to the animals
Image 2: Data extraction table for nutritional content of each ingredient or diets
Image 2: Data extraction table for nutritional content of each ingredient or diets
Image 3: Data extraction table for digestibility of the ingredients or diets
Image 3: Data extraction table for digestibility of the ingredients or diets
  1. Make.Trt = create & name treatments by combining the experimental practices entered in the practice tabs.

  2. EnterData = Captures values and associated errors for the experimental treatments, products, outcomes and times specified in the previous tabs. Do not start data entry until you’ve completed all the previous tabs.

Data extractors went through an intensive 3 week training that included video tutorials and practical examples of extracting data with the livestock template.

Training materials can be found here: https://cgiar-my.sharepoint.com/:f:/g/personal/p_steward_cgiar_org/EmOgDnJmyX9KkD1s8rNqggsBlSDMvTavst0gd7VIwU3EMw?e=c1gHDf

Livestock ontology

As part of the extraction process of the ERA Livestock, we created an ontology. The livestock ontology is a structured, hierarchical framework that defines and categorizes terms, concepts, and relationships related to livestock systems. It includes standardized definitions for livestock species, breeds, production systems, management practices, feed types, environmental factors, health indicators, and outcomes. By providing a shared vocabulary, livestock ontology facilitates consistent and comprehensive data representation across studies.

Link to the ontology: https://doi.org/10.7910/dvn/75e7hv

Exploring the data

Importing the data

Downloading the data from the S3 bucket

The data can be downloading using the following code:

#download   most    recent  version of  the data    

#   Set up  connection  to  S3  bucket
  dl_dir<-"downloaded_data"
  s3<-s3fs::S3FileSystem$new(anonymous = T)
  era_s3<-"s3://digital-atlas/era"
  
  # List the files in the s3 bucket
  files<-s3$dir_ls(file.path(era_s3,"data"))
  # This is the most recent version of the datas3://digital-atlas/era/data/skinny_cow_2022-YYYY-MM-DD.RData (substitute most recent date into filepath)
  files<-tail(grep(".RData",grep("skinny_cow_2022",files,value=T),value=T),1)
  
  # Set a save location for the dataset (amend to something more suitable for your needs)
  save_path<-file.path(getwd(),dl_dir,basename(files))
  
  if(!file.exists(save_path)){
    s3$file_download(files,save_path,overwrite = T)
  }
  
  livestock_metadata<- miceadds::load.Rdata2(file=basename(save_path),path=dirname(save_path))

Subsetting the ERA Compiled data

The Evidence for Resilient Agriculture (ERA) dataset provides a comprehensive analysis of the impacts of technology adoption on 87 key indicators spanning productivity, resilience, and climate change mitigation. This dataset integrates data from both agronomy and livestock studies, with a focus on creating control-versus-treatment comparisons to enable robust meta-analysis.

To extract insights specific to livestock, it is necessary to subset the dataset to isolate livestock-related studies, as follows (unhide the code):

# Subset data
livestock_data<-ERA.Compiled[!is.na(Date)]
# Subset to fewer themes to simplify plot
livestock_data<-livestock_data[Product.Type %in% c("Animal")]

Understanding the descriptions of major ERA concepts

Practice codes

# Filter the data
filtered_data_prac <- ERAg::PracticeCodes %>%
  filter(Theme == "Animals")

# Display the filtered data in a scrollable table
DT::datatable(
  filtered_data_prac,
  options = list(
    scrollY = "400px",    # Set vertical scroll height
    scrollX = TRUE,       # Enable horizontal scrolling
    pageLength = 10,      # Display 10 rows per page
    fixedHeader = FALSE   # Disable fixed headers
  )
)

Outcome Codes

DT::datatable(
  head(ERAg::OutcomeCodes),  # Display the first few rows of PracticeCodes
  options = list(
    scrollY = "400px",    # Set vertical scroll height
    scrollX = TRUE,       # Enable horizontal scrolling
    pageLength = 10,      # Display 10 rows per page
    fixedHeader = FALSE   # Disable fixed headers
  )
)

Products

# Filter the data
filtered_data_eu <- ERAg::EUCodes %>%
  filter(Product.Type == "Animal")

# Display the filtered data in a scrollable table
DT::datatable(
  filtered_data_eu,
  options = list(
    scrollY = "400px",    # Set vertical scroll height
    scrollX = TRUE,       # Enable horizontal scrolling
    pageLength = 10,      # Display 10 rows per page
    fixedHeader = FALSE   # Disable fixed headers
  )
)

Exploring geographic locations of studies available

This dataset represents spatial information about livestock-related research papers across various countries in Africa. Each point on the map corresponds to a geographic location associated with a research paper, categorized by livestock type (e.g., cattle, goat, sheep, etc.). The dataset includes:

Country: The country where the research is associated. Latitude and Longitude: Coordinates representing the location of the research. Product.Simple: The type of livestock being studied. Counts: The number of papers associated with each location (aggregated for the map). This data provides an overview of the geographic distribution and focus of livestock research, enabling users to explore patterns and trends by livestock type and region.

# Create a leaflet map with interactive filtering
# Subset the livestock data
site_data <- livestock_data %>%
  dplyr::select(Product.Simple, Country, Latitude, Longitude) %>%
  distinct() %>%
  mutate(
    Longitude = as.numeric(Longitude),
    Latitude = as.numeric(Latitude)
  ) %>%
  filter(!is.na(Longitude) & !is.na(Latitude))  # Remove rows with missing coordinates

# Count the number of records per country
livestock_counts <- site_data %>%
  group_by(Country,Product.Simple) %>%
  summarise(N_Livestock = n())

# Prepare the world map with only African countries
world <- ne_countries(scale = "medium", returnclass = "sf") %>%
  filter(continent == "Africa") %>%  # Filter for African continent only
  mutate(admin = if_else(admin == "United Republic of Tanzania", "Tanzania", admin))

# Ensure the CRS is consistent (EPSG:4326)
world <- st_transform(world, crs = 4326)

# Convert site data to spatial format (only for African countries)
site_data_filtered <- site_data %>%
  filter(Country %in% world$admin) %>%  # Filter site data for African countries
  st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326, remove = FALSE)

# Join livestock counts with African country geometries for mapping
countries_studies <- world %>%
  dplyr::select(admin, geometry) %>%
  rename(Country = admin) %>%
  left_join(livestock_counts, by = "Country")
library(ggplot2)

# Filter data if necessary (e.g., removing missing values or specific subsets)
filtered_data <- site_data_filtered

# Create a static plot
static_plot <- ggplot() +
  # Base map with neutral colors
  geom_sf(data = countries_studies, fill = "gray92", color = "white") +
  
  # Points for each product type, with colors determined by the product
  geom_point(data = filtered_data, 
             aes(x = Longitude, y = Latitude, color = Product.Simple), 
             size = 3, alpha = 0.8) +
  
  # Add annotation for context
  annotate("text", x = 40, y = -30, label = "One Point = One Paper", 
           color = "#000000", size = 5, hjust = 0) +
  
  # Customize the plot's appearance
  theme_minimal() +
  theme(
    axis.line = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    legend.title = element_text(size = 12, face = "bold"),
    legend.text = element_text(size = 10),
    legend.position = "right"  # Place the legend on the right
  ) +
  
  # Set coordinate limits for the map
  coord_sf(xlim = c(-20, 95), ylim = c(-40, 40), expand = FALSE) +
  
  # Add legend title
  labs(color = "Livestock Type", 
       title = "Distribution of Livestock Research Papers", 
       subtitle = "Each point represents a research paper")

# Display the static plot
print(static_plot)

Animals reported within papers

The treemap represents the distribution of livestock categories reported within research papers that were extracted in ERA. Each rectangle corresponds to a livestock category, and its size is proportional to the number of papers reporting on that category. Here’s an analysis of the data shown:

Dominant Categories:

Sheep: The largest rectangle (120 papers) indicates that sheep are the most frequently reported livestock category in the dataset. This could reflect their significant role in agricultural research and practices.

Goats: Goats follow closely with 91 papers, showing their importance, likely due to their adaptability to diverse environments.

Moderately Represented Categories:

Cattle (96 papers) and Fish (71 papers) are also prominent, reflecting their widespread use in agricultural systems, both for food production and other economic activities.

# Prepare data for the treemap
products <- livestock_data %>%
  distinct(Product.Simple, Code) %>%  # Keep only unique combinations
  group_by(Product.Simple) %>%
  summarise(Row_Count = n(), .groups = "drop")  # Count occurrences per category

# Create the static treemap
static_treemap <- ggplot(products, aes(
  area = Row_Count,  # Size of rectangles based on row count
  fill = Row_Count,  # Fill color based on row count
  label = Product.Simple  # Labels for each rectangle
)) +
  geom_treemap() +
  geom_treemap_text(
    colour = "white",  # Text color
    place = "center",  # Place text at the center of rectangles
    grow = TRUE  # Adjust text size to fit rectangles
  ) +
  scale_fill_viridis_c() +  # Apply Viridis color scale
  labs(
    title = "Distribution of Livestock Types",  # Plot title
    fill = "Row Count"  # Legend title
  ) +
  theme_minimal()

# Display the static treemap
print(static_treemap)

Outcomes reported

Outcome measures, units, and products were extracted as reported. Outcome codes differentiated plant parts (grain vs stover) and products from the same species (milk versus meat). Oftentimes authors discussed many treatments but only reported a few. The ways in which the outcomes were reported in the papers, by year or aggregation across practices, dictated which data were extracted and how treatments were coded. Experimental Units (EU) described the species or product that were measured (e.g., maize grain).

# Aggregate data by pillar and indicator
DATA_OUTCOMES <- livestock_data %>%
  group_by(Out.Pillar, Out.Ind) %>%
  summarise(N_Livestock = n_distinct(Code), .groups = "drop") %>%
  rename(Pillar = Out.Pillar, Indicator = Out.Ind)

# Sort indicators within each pillar for better organization
DATA_OUTCOMES <- DATA_OUTCOMES %>%
  arrange(Pillar, Indicator) %>%
  mutate(
    Indicator = factor(Indicator, levels = unique(Indicator)),
    Pillar = factor(Pillar, levels = c("Productivity", "Resilience", "Mitigation"))
  )

# Define hover information for specific indicators
hover_info <- tibble(
  Indicator = c("Product Yield", "Income", "Economic Performance", "Costs", "Soil Quality", "Efficiency"),
  HoverDetails = c("Meat yield; Egg yield; Milk yield; Reproductive yield; Weight gain", "Gross return; Gross margin; Net return", "Benefit Cost Ratios", "Labour cost; Total cost; Fixed cost; Variable cost", "Soil Erosion; Soil Nitrogen; Soil Organic Carbon", "Feed Conversion Ratios; Protein Conversion Ratios; Nitrogen Apparent Efficiency")
)

# Add hover text to the data
DATA_OUTCOMES <- DATA_OUTCOMES %>%
  left_join(hover_info, by = "Indicator") %>%  # Join hover info
  mutate(
    HoverText = ifelse(
      !is.na(HoverDetails),
      paste0(Indicator, "\n", HoverDetails, "\nCount: ", N_Livestock),
      paste0(Indicator, "\nCount: ", N_Livestock)
    )
  )

# Define custom colors for each pillar
pillar_colors <- c(
  "Productivity" = "#FFCC66",
  "Resilience" = "#990000",
  "Mitigation" = "#8B4513"
)

# Create the static faceted bar plot
static_plot <- ggplot(DATA_OUTCOMES, aes(
  x = Indicator, y = N_Livestock, fill = Pillar
)) +
  geom_col(width = 0.8) +  # Vertical bars
  labs(
    y = "Number of Papers",
    x = "Outcome Indicator",
    title = "Number of Papers by Outcome Indicator and Pillar"
  ) +
  scale_fill_manual(values = pillar_colors, na.value = "gray70") +
  scale_y_continuous(limits = c(0, max(DATA_OUTCOMES$N_Livestock) + 50), expand = c(0, 0)) +
  facet_wrap(~Pillar, scales = "free_x", nrow = 1) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(size = 10, angle = 45, hjust = 1),  # Rotate x-axis labels
    axis.text.y = element_text(size = 10),  # Adjust y-axis labels
    axis.title.x = element_text(size = 12, face = "bold", margin = margin(t = 10)),  # Add margin
    axis.title.y = element_text(size = 12, face = "bold"),  # Y-axis title styling
    legend.position = "none",  # Remove legend
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    strip.text = element_text(size = 12, face = "bold"),  # Facet strip labels styling
    plot.margin = margin(10, 10, 10, 10)  # Reduced margins
  )

# Display the static plot
print(static_plot)

Use Case: Understanding the impact of tree fodders on feed intake and weight gain

The objective of this analysis is to systematically analyze and explore the impact of livestock feeding practices, particularly tree fodder addition and substitution, on key outcomes (e.g., weight gain, feed intake). To achieve this, we will follow these steps:

1. Loading Required Libraries and Functions as shown earlier in this vignette. This will require the most recent version of the data, which will come from the S3 bucket

2.Data Cleaning and Filtering

2.1 Sub-setting the data to specific livestock (e.g., cattle, sheep, goats) and practices involving tree fodder addition or substitution.

2.2 Harmonizing Units: Converts weight units (e.g., kg to g per individual per day) for consistent analysis.

2.3 Exploring Practices and Outcomes: Summarizes data availability at the sub-practice and practice levels

3. Linking Observations to Metadata: The script links experimental data with metadata to understand: The specific diet fed to animals, nutritional composition and digestibility of the diet, Key fields in the metadata that describe treatments and practices.

4. Plotting simple figures

4.1 Plotting weight gain distribution with outliers

4.2 Plotting weight gain distribution without outliers

PLEASE UNHIDE THE CODES TO VIEW. You can use these to tailor to your own needs

1. Loading and saving the data

This section retrieves the most recent version of the livestock dataset from an S3 bucket. It lists the available files, downloads the required .RData file, and loads it into R using miceadds::load.Rdata2. The objective is to prepare the dataset (livestock_metadata) for analysis.

# First we need to get the detailed dataset containing the management information that relates to the experiment, this is in the Atlas S3 Bucket

  dl_dir<-"downloaded_data"
  s3<-s3fs::S3FileSystem$new(anonymous = T)
  era_s3<-"s3://digital-atlas/era"
  
  # List the files in the s3 bucket
  files<-s3$dir_ls(file.path(era_s3,"data"))
  # This is the most recent version of the datas3://digital-atlas/era/data/skinny_cow_2022-YYYY-MM-DD.RData (substitute most recent date into filepath)
  files<-tail(grep(".RData",grep("skinny_cow_2022",files,value=T),value=T),1)
  
  # Set a save location for the dataset (amend to something more suitable for your needs)
  save_path<-file.path(getwd(),dl_dir,basename(files))
  
  if(!file.exists(save_path)){
    s3$file_download(files,save_path,overwrite = T)
  }
  
  livestock_metadata<- miceadds::load.Rdata2(file=basename(save_path),path=dirname(save_path))

2. Data cleaning and subsetting

2.1 Subsetting the data

section focuses on filtering the dataset to a specific scope for analysis. It begins by identifying subpractices related to “Feed Addition” and “Feed Substitution” within the “Animals” theme, specifically those involving agroforestry. The data is then narrowed to livestock types of interest, such as cattle, goats, and sheep, and further refined to focus on key productivity outcomes, including “Meat Yield,” “Weight Gain,” and “Milk Yield.” The latest version of the dataset, stored as a .parquet file in the S3 bucket, is downloaded and processed using the same subsetting logic. Confounding practices, such as “Concentrates” and “Feed Crop,” are excluded to improve data quality.

focal_pracs<-PracticeCodes[Practice %in% c("Feed Addition","Feed Substitution") 
                            & grepl("Agrofor",Subpractice),Code]

data<-ERA.Compiled[grepl(paste(focal_pracs,collapse = "|"),plist)]

  # 1.2) Subset to cattle and small ruminants #####
  focal_prods<-c("Cattle","Goat","Sheep")
  
  data<-data[Product.Simple %in% focal_prods]
  
  # 1.3) Subset to outcomes of interest  #####
  focal_out<-c("Meat Yield","Weight Gain","Milk Yield")
  
  data<-data[Out.SubInd %in% focal_out]
  

# List the files in the s3 bucket
files<-s3$dir_ls(file.path(era_s3,"data"))
# This should be the most recent version of the data era_compiled-v1.0_2018-v1.1_2020-skinny_cow_2022_YYYY_MM_DD.parquet
files<-tail(grep("parquet",grep("era_compiled",files,value=T),value=T),1)

# Set a save location for the dataset (amend to something more suitable for your needs)
save_path<-file.path(getwd(),dl_dir,basename(files))

if(!file.exists(save_path)){
  s3$file_download(files,save_path,overwrite = T)
}

ERA.Compiled_new<-arrow::read_parquet(save_path)
data_new<-ERA.Compiled_new[Version=="skinny_cow_2022" & grepl(paste(focal_pracs,collapse = "|"),plist)]

# Remove confounding subpractices
data_new<-data_new[!grepl("Concentrates|Feed Crop|Breed|Feed NonCrop",SubPrName)]

# The newer dataset on the s3 should be superior to old dataset so let's use it
data<-data_new

# Remove mechanical processing (this is just going to be chopping tree forages, probably not of interest)
  data[,SubPrName:=gsub("-Feed Mech Process|-Grazing Cut & Carry","",SubPrName)]
  
# Looking at any practices than involve tree fodder addition or substitution
  data<-data[,tree_fodder_add:=F][grepl("Feed AgFor (Add)",SubPrName,fixed=T),tree_fodder_add:=T]
  data<-data[,tree_fodder_sub:=F][grepl("Feed AgFor (Sub)",SubPrName,fixed=T),tree_fodder_sub:=T]

2.2 Harmonizing units

Unit harmonization is essential when studying livestock papers to ensure consistency and comparability across diverse datasets. In livestock research, data on outcomes like feed intake or weight gain are often reported in various units, such as kilograms (kg), grams per individual per day (g/individual/day), or other measurement standards. Without harmonization, direct comparisons or meta-analyses become challenging, as the variability in units can introduce bias or inaccuracies in the interpretation of results. By standardizing units, such as converting weight data from kg to g/day or normalizing by the duration of the study, researchers can create a uniform dataset. This allows for meaningful cross-study comparisons, improved statistical analysis, and clearer insights into the impacts of specific practices on livestock productivity, such as weight gain or feed efficiency.

# 3.2) Harmonize units #####
  data[Units=="kg" & !is.na(Duration),c("MeanT","MeanC","Units"):=.(round(1000*MeanT/(365*Duration),2),round(1000*MeanC/(365*Duration),2),"g/individual/day")
              ][Units=="kg/individual/day",c("MeanT","MeanC","Units"):=.(round(1000*MeanT,2),round(1000*MeanC,2),"g/individual/day")]

2.3 Exploring the subsetted data

After subsetting the data, you can explore the number of remaining papers that are within your research focus. The following table The table provides insights into the data coverage for different livestock practices, products, and outcomes. For example, “Feed Addition” applied to “Goat” for “Weight Gain” is reported in 15 studies with 48 observations from 6 countries. This information can help identify well-studied areas and data gaps in livestock research

We can choose to explore the data in future detail. The table below shows the studies that looked at the impact of adding tree fodders to diets of cattle goat and sheep.

The table below shows the studies that looked at the impact of substitution of other ingredient types with tree fodders to diets of cattle goat and sheep.

3. Linking observations to the metadata

As mentioned in the methods section, each table in the extraction excel template creates a seperate table in the data structure. Therefore, when using the metadata (which are the original seperate tables) we need to merge the tables that we are interested in.

Image 4: Data structure of diets
Image 4: Data structure of diets
Image 5: Data structure of diet ingredients
Image 5: Data structure of diet ingredients

Below are the individual tables for diets, nutrition and digestibility. We will then explore how to merge information from the different tables. To understand what the field are in each table download the follow excel sheet and navigate to the era_fields tab https://github.com/peetmate/era_codes/raw/main/era_master_sheet.xlsx

  
  # 4.2) Explore  metadata #####
  # This table is a high level description of the diet
  diet_summary<-livestock_metadata$Animals.Out
  
    diet_ingredients<-livestock_metadata$Animals.Diet
  head(diet_ingredients)
#>    D.Item.AOM  D.ItemxProcess_low A.Level.Name               D.Type
#>        <char>              <char>       <char>               <char>
#> 1: AOM_001911                 hay         Base   Herbaceous Fodders
#> 2: AOM_000604    groundnut haulms     150g/day       Crop Byproduct
#> 3: AOM_000604    groundnut haulms     300g/day       Crop Byproduct
#> 4: AOM_000604    groundnut haulms     450g/day       Crop Byproduct
#> 5: AOM_001901 atriplex nummularia         Base Agroforestry Fodders
#> 6: AOM_000647        barley grain           T2         Crop Product
#>                   D.Item D.Item.Group D.Source D.Process DC.Is.Dry D.Amount
#>                   <char>       <char>   <char>    <list>    <char>    <num>
#> 1: Unspecified Grass Hay         <NA>     <NA>        NA       Yes       NA
#> 2:       Groundnut Haulm         <NA>     <NA>        NA       Yes      150
#> 3:       Groundnut Haulm         <NA>     <NA>        NA       Yes      300
#> 4:       Groundnut Haulm         <NA>     <NA>        NA       Yes      450
#> 5:   Atriplex nummularia         <NA>     <NA>        NA      <NA>       NA
#> 6:          Barley Grain         <NA>     <NA>        NA      <NA>      400
#>    D.Ad.lib D.Unit.Amount D.Unit.Time D.Unit.Animals D.Day.Start D.Day.End
#>      <char>        <char>      <char>         <char>      <lgcl>    <char>
#> 1:      Yes          g/kg         day     individual          NA      <NA>
#> 2:       No             g         day     individual          NA      <NA>
#> 3:       No             g         day     individual          NA      <NA>
#> 4:       No             g         day     individual          NA      <NA>
#> 5:      Yes          <NA>         day           <NA>          NA      <NA>
#> 6:     <NA>             g         day           <NA>          NA      <NA>
#>    B.Code          D.Item.Raw      D.ItemxProcess D.Is.Group
#>    <char>              <char>              <char>     <lgcl>
#> 1: NN0022                 Hay                 Hay      FALSE
#> 2: NN0022    Groundnut Haulms    Groundnut Haulms      FALSE
#> 3: NN0022    Groundnut Haulms    Groundnut Haulms      FALSE
#> 4: NN0022    Groundnut Haulms    Groundnut Haulms      FALSE
#> 5: NN0080 Atriplex nummularia Atriplex nummularia      FALSE
#> 6: NN0080        Barley Grain        Barley Grain      FALSE
#>       D.Item.Root.Comp D.Item.Root.Comp.Proc_Major
#>                 <char>                      <char>
#> 1:   Unspecified Grass     Unspecified Grass Dried
#> 2:     Groundnut Haulm             Groundnut Haulm
#> 3:     Groundnut Haulm             Groundnut Haulm
#> 4:     Groundnut Haulm             Groundnut Haulm
#> 5: Atriplex nummularia         Atriplex nummularia
#> 6:        Barley Grain                Barley Grain
#>    D.Item.Root.Other.Comp.Proc_All D.Item.Other D.Item.Proc_All
#>                             <char>       <char>          <char>
#> 1:           Unspecified Grass Hay         <NA>             Hay
#> 2:                 Groundnut Haulm         <NA>            <NA>
#> 3:                 Groundnut Haulm         <NA>            <NA>
#> 4:                 Groundnut Haulm         <NA>            <NA>
#> 5:             Atriplex nummularia         <NA>            <NA>
#> 6:                    Barley Grain         <NA>            <NA>
#>    D.Item.Proc_Major D.Item.Proc_Minor D.Item.Comp
#>               <char>            <char>      <char>
#> 1:             Dried              <NA>        <NA>
#> 2:              <NA>              <NA>       Haulm
#> 3:              <NA>              <NA>       Haulm
#> 4:              <NA>              <NA>       Haulm
#> 5:              <NA>              <NA>        <NA>
#> 6:              <NA>              <NA>       Grain
#>                                                                           AOM.Terms
#>                                                                              <char>
#> 1: Forage Plants/Cereal and Grass Forages/Unspecified Grass/Unspecified Grass Dried
#> 2:                       Crop Byproduct/Legume ByProducts/Groundnut/Groundnut Haulm
#> 3:                       Crop Byproduct/Legume ByProducts/Groundnut/Groundnut Haulm
#> 4:                       Crop Byproduct/Legume ByProducts/Groundnut/Groundnut Haulm
#> 5:                                   Forage Plants/Forage Trees/Atriplex nummularia
#> 6:                                 Crop Product/Cereal Products/Barley/Barley Grain
#>    AOM.Scientific.Name D.Item.Is.Tree          D.Item.raw
#>                 <char>         <lgcl>              <char>
#> 1:                <NA>          FALSE                 Hay
#> 2:    Arachis hypogaea          FALSE    Groundnut Haulms
#> 3:    Arachis hypogaea          FALSE    Groundnut Haulms
#> 4:    Arachis hypogaea          FALSE    Groundnut Haulms
#> 5: Atriplex nummularia           TRUE Atriplex nummularia
#> 6:     Hordeum vulgare          FALSE        Barley Grain
  
  diet_nutrition<-livestock_metadata$Animals.Diet.Comp
  head(diet_nutrition)
#>      B.Code                    D.Item DC.Unit.Is.Dry is_group is_entire_diet
#>      <char>                    <char>         <char>   <lgcl>         <lgcl>
#> 1:   NN0005                       0 M            Yes    FALSE           TRUE
#> 2: HK0066.1                     0 MSK    Unspecified    FALSE           TRUE
#> 3: HK0066.2                     0 MSK    Unspecified    FALSE           TRUE
#> 4:   HK0330        0 g/kg A. tortilis            Yes    FALSE           TRUE
#> 5:   NJ0003               0 g/kg CBLE            Yes    FALSE           TRUE
#> 6:   HK0326 0 g/kg potato hash silage            Yes    FALSE           TRUE
#>    D.Item.Root.Comp.Proc_Major D.Item.Root.Other.Comp.Proc_All D.Item.AOM
#>                         <char>                          <char>     <char>
#> 1:                        <NA>                            <NA>       <NA>
#> 2:                        <NA>                            <NA>       <NA>
#> 3:                        <NA>                            <NA>       <NA>
#> 4:                        <NA>                            <NA>       <NA>
#> 5:                        <NA>                            <NA>       <NA>
#> 6:                        <NA>                            <NA>       <NA>
#>    DC.Value DC.Unit   DC.Method DC.Variable                D.Item.raw
#>       <num>  <char>      <char>      <char>                    <char>
#> 1:   876.00    g/kg    Measured          DM                       0 M
#> 2:   921.00    g/kg    Measured          DM                     0 MSK
#> 3:   881.00    g/kg    Measured          DM                     0 MSK
#> 4:   867.00    g/kg    Measured          DM        0 g/kg A. tortilis
#> 5:    90.84       % Unspecified          DM               0 g/kg CBLE
#> 6:   886.00    g/kg    Measured          DM 0 g/kg potato hash silage
  
  diet_digestibility<-livestock_metadata$Animals.Diet.Digest
  head(diet_digestibility)
#>    B.Code            D.Item DD.Unit.Is.Dry is_group is_entire_diet
#>    <char>            <char>         <char>   <lgcl>         <lgcl>
#> 1: AN0057             0 PPL            Yes    FALSE           TRUE
#> 2: LM0104  0% A. sieberiana            Yes    FALSE           TRUE
#> 3: HK0033 0% Brewer's Grain    Unspecified    FALSE           TRUE
#> 4: EO0046            0% CFL            Yes    FALSE           TRUE
#> 5: HK0108  0% Leucaena Diet    Unspecified    FALSE           TRUE
#> 6: HK0008  0% Leucaena Goat    Unspecified    FALSE           TRUE
#>    D.Item.Root.Comp.Proc_Major D.Item.Root.Other.Comp.Proc_All D.Item.AOM
#>                         <char>                          <char>     <char>
#> 1:                        <NA>                            <NA>       <NA>
#> 2:                        <NA>                            <NA>       <NA>
#> 3:                        <NA>                            <NA>       <NA>
#> 4:                        <NA>                            <NA>       <NA>
#> 5:                        <NA>                            <NA>       <NA>
#> 6:                        <NA>                            <NA>       <NA>
#>    DD.Value     DD.Unit DD.Nut.or.Diet
#>       <num>      <char>         <char>
#> 1:     0.57 Coefficient       Nutrient
#> 2:    57.80           %       Nutrient
#> 3:    69.86           %       Nutrient
#> 4:   530.90        g/kg       Nutrient
#> 5:    71.75           %       Nutrient
#> 6:    50.80           %       Nutrient
#>                                         DD.Method DD.Variable        D.Item.raw
#>                                            <char>      <char>            <char>
#> 1:            Measured total collection techinque          DM             0 PPL
#> 2:                                    Unspecified          DM  0% A. sieberiana
#> 3: Measured total collection techinque (Apparent)          DM 0% Brewer's Grain
#> 4:            Measured total collection techinque          DM            0% CFL
#> 5: Measured total collection techinque (Apparent)          DM  0% Leucaena Diet
#> 6:                                    Unspecified          DM  0% Leucaena Goat

Diet ingredients table

  # Display the summary table   of  diets
DT::datatable(
  diet_ingredients,
  options = list(
    scrollY = "400px",  # Set vertical scroll height
    scrollX = TRUE,     # Enable horizontal scrolling
    pageLength = 20,    # Initial number of rows displayed
    fixedHeader = FALSE  # Keep column headers fixed while scrolling
  )
)

Diet nutrition table


DT::datatable(
  diet_nutrition,
  options = list(
    scrollY = "400px",  # Set vertical scroll height
    scrollX = TRUE,     # Enable horizontal scrolling
    pageLength = 20,    # Initial number of rows displayed
    fixedHeader = FALSE  # Keep column headers fixed while scrolling
  )
)

Diet digestibility table

  # Display the summary table   of  diets
DT::datatable(
  diet_digestibility,
  options = list(
    scrollY = "400px",  # Set vertical scroll height
    scrollX = TRUE,     # Enable horizontal scrolling
    pageLength = 20,    # Initial number of rows displayed
    fixedHeader = FALSE  # Keep column headers fixed while scrolling
  )
)

3.1 Combining feed intake and weight gain outcomes

This script (unhide) integrates feed intake and weight gain data for livestock to analyze the relationship between feed types, including tree species, and animal performance.

It starts by filtering the feed intake data to include only entire diets with non-missing values. Tree species associated with feed intake are then merged into the dataset.

Similarly, weight gain data for non-fish species is filtered, standardized by converting weight measurements into kilograms per day, and calculating the final weight (end weight) after a given period. The script then merges the feed intake data with the weight gain data using common identifiers.

This results in a unified dataset that combines feed intake (including tree species) with corresponding weight gain metrics for livestock, enabling detailed analysis of the impacts of different feed practices on animal growth.

# 4.5) Feed Intake and Weight Gain with Tree Species #####

# Filter Feed Intake data to include only entire diets and remove NA values
feed_intake <- livestock_metadata$Data.Out[
  Out.Subind == "Feed Intake" & is_entire_diet == TRUE & !is.na(ED.Intake.Item), 
  .(B.Code, T.Name, A.Level.Name, Out.Subind, ED.Intake.Item, ED.Mean.T, Out.Unit)
]


# Select only relevant columns for feed trees and rename
feed_trees <- data %>% 
  select(Code, T.Descrip, Tree.Feed) %>% 
  rename(`A.Level.Name` = T.Descrip, `B.Code` = Code)

# Merge feed intake with tree species data
feed_intake_trees <- merge(
  feed_intake,
  feed_trees,
  by = c("B.Code", "A.Level.Name"),
  all.x = TRUE  # Left join to retain all feed intake rows
)

# Filter Weight Gain data and remove fish-related entries
WG <- livestock_metadata$Data.Out[
  Out.Subind == "Weight Gain" & P.Product != "Fish", 
  .(B.Code, P.Product, T.Name, A.Level.Name, Out.WG.Start, Out.WG.Unit, Out.WG.Days, ED.Mean.T, Out.Unit)
]

# Define units to standardize and convert Weight Gain data
units_per_day <- c(
      "g/day", "g", "g/individual/day", "g/head/day", "g/day/individual", 
      "g/d/individual", "g/individual/d", "g/indivividual/day", "g/individual", 
      "g/ndividual/day", "g/dindividual/day", "g/individual.day", "g /individual/day"
    )
    
# Convert ED.Mean.T to kilograms/day only for specific units
    WG[, ED.Mean.T_kg := ifelse(
      Out.Unit %in% units_per_day,               # Check if Out.Unit is in the list
      round(ED.Mean.T / 1000, 3),                   # Convert grams/day to kilograms/day and round
      round(ED.Mean.T, 3)                           # Retain as is if not in the list
    )]
    
    # Convert Out.WG.Start to kilograms if Out.WG.Unit indicates grams
    WG[, Out.WG.Start_kg := ifelse(
      grepl("^g$", Out.WG.Unit, ignore.case = TRUE), # Match exact "g"
      Out.WG.Start / 1000,                          # Convert grams to kilograms
      Out.WG.Start                                   # Retain if already in kilograms
    )]
    
    # Calculate Out.WG.End
    WG[, Out.WG.End := ifelse(
      Out.Unit %in% units_per_day,                  # Daily gain units
      round(Out.WG.Start_kg + (ED.Mean.T_kg * Out.WG.Days), 3),
      ifelse(                                       # Non-daily gain units
        grepl("^(g|kg|Kg)$", Out.Unit, ignore.case = TRUE),
        round(Out.WG.Start_kg + ED.Mean.T_kg, 3),
        NA                                          # Set to NA for other units
      )
    )]
 #Merge with feed intake. 
    # Rename columns in WG and feed intake datasets
    WG <- WG %>%
      rename(
        `Weight Gain` = ED.Mean.T,
        `Weight Gain Unit` = Out.Unit,
        `Weight Gain_kg` = ED.Mean.T_kg
      )
    
    feed_intake_trees <- feed_intake_trees %>%
      rename(
        `Feed Intake` = ED.Mean.T,
        `Feed Intake Unit` = Out.Unit,
      )
    
    # Perform an inner join on the common columns
    intake_WG <- merge(
      WG, feed_intake_trees,
      by = c("B.Code", "T.Name", "A.Level.Name"),
      all = FALSE # Inner join: retain only matching rows
    )
    
    intake_WG<- intake_WG %>%
      rename(`D.Item.raw`= ED.Intake.Item)
    
  # Display the summary table   of  diets
DT::datatable(
  intake_WG,
  options = list(
    scrollY = "400px",  # Set vertical scroll height
    scrollX = TRUE,     # Enable horizontal scrolling
    pageLength = 20,    # Initial number of rows displayed
    fixedHeader = FALSE  # Keep column headers fixed while scrolling
  )
)

3.2 Adding nutrion information

This script performs a detailed analysis by merging data on livestock feed intake, weight gain, and nutritional composition to create a comprehensive dataset. First, it renames the ED.Intake.Item column to D.Item_raw in the intake_WG dataset for consistency. Then, it filters the livestock_metadata$Animals.Diet.Comp dataset to exclude rows with missing values in the DC.Value column, ensuring only complete nutritional data is used. Relevant columns (B.Code, DC.Value, DC.Unit, DC.Variable, D.Item_raw) are selected from this filtered dataset. The script merges the nutritional data with the feed intake and weight gain dataset (intake_WG) using an inner join, retaining only rows with matching values in D.Item_raw and B.Code

  nutrition <- livestock_metadata$Animals.Diet.Comp %>% 
    filter(!is.na(DC.Value)) %>%  # Omit rows with NA in DC.Value
    select(B.Code, DC.Value, DC.Unit, DC.Variable, D.Item.raw)
  
  intake_WG_nut <- merge(
    nutrition, intake_WG,
    by = c("D.Item.raw", "B.Code"),
    all = FALSE  # Inner join: retain only matching rows
  )
  
  DT::datatable(
    intake_WG_nut,
    options = list(
      scrollY = "400px",  # Set vertical scroll height
      scrollX = TRUE,     # Enable horizontal scrolling
      pageLength = 20,    # Initial number of rows displayed
      fixedHeader = FALSE # Keep column headers fixed while scrolling
    )
  )

4. Plotting simple figures

4.1 Plotting weight gain distribution with outliers

This script creates a Shiny app that allows users to visualize the weight gain distribution of three livestock categories: “Cattle,” “Goat,” and “Sheep,” with outliers included. The dataset WG is filtered to include only rows where the P.Product column matches the selected animal.

# Function to filter data for all animals and include outliers
filter_all_animals <- function(data) {
  # Subset data for selected animals
  animal_data <- data[data$P.Product %in% c("Cattle", "Goat", "Sheep"), ]
  return(animal_data)
}

# Filter the data for all animals
animal_data_with_outliers <- filter_all_animals(WG)

# Create individual plots for each animal with outliers
plot_cattle <- ggplot(animal_data_with_outliers[animal_data_with_outliers$P.Product == "Cattle", ], aes(x = P.Product, y = `Weight Gain_kg`)) +
  geom_boxplot(outlier.color = "red", outlier.shape = 19) +
  labs(
    x = "Animal Type",
    y = "Weight Gain (kg/day)"
  ) +
  theme_minimal()

plot_goat <- ggplot(animal_data_with_outliers[animal_data_with_outliers$P.Product == "Goat", ], aes(x = P.Product, y = `Weight Gain_kg`)) +
  geom_boxplot(outlier.color = "red", outlier.shape = 19) +
  labs(
    x = "Animal Type",
    y = "Weight Gain (kg/day)"
  ) +
  theme_minimal()

plot_sheep <- ggplot(animal_data_with_outliers[animal_data_with_outliers$P.Product == "Sheep", ], aes(x = P.Product, y = `Weight Gain_kg`)) +
  geom_boxplot(outlier.color = "red", outlier.shape = 19) +
  labs(
    x = "Animal Type",
    y = "Weight Gain (kg/day)"
  ) +
  theme_minimal()

# Combine the plots into one image in landscape orientation
combined_plot <- grid.arrange(plot_cattle, plot_goat, plot_sheep, nrow = 1)


# Display the combined plot
print(combined_plot)
#> TableGrob (1 x 3) "arrange": 3 grobs
#>   z     cells    name           grob
#> 1 1 (1-1,1-1) arrange gtable[layout]
#> 2 2 (1-1,2-2) arrange gtable[layout]
#> 3 3 (1-1,3-3) arrange gtable[layout]

4.2 Plotting weight gain distribution without outliers

This script creates a Shiny app that allows users to visualize the weight gain distribution of three livestock categories: “Cattle,” “Goat,” and “Sheep,” with outliers excluded. The dataset WG is filtered to include only rows where the P.Product column matches the selected animal. To remove outliers, the script applies the Interquartile Range (IQR) method, calculating the first quartile (Q1), third quartile (Q3), and IQR. Data points falling outside the range of Q1 - 1.5 * IQR to Q3 + 1.5 * IQR are excluded. A box plot, generated using ggplot2, dynamically displays the weight gain distribution for the selected animal, providing a clean and focused view without the influence of extreme values

library(ggplot2)
library(gridExtra)

# Function to filter data for all animals and remove outliers
filter_and_remove_outliers <- function(data) {
  # Subset data for selected animals
  animal_data <- data[data$P.Product %in% c("Cattle", "Goat", "Sheep"), ]
  
  # Remove outliers for each animal type
  animal_data <- animal_data %>%
    group_by(P.Product) %>%
    filter(
      `Weight Gain_kg` > quantile(`Weight Gain_kg`, 0.25, na.rm = TRUE) - 1.5 * IQR(`Weight Gain_kg`, na.rm = TRUE) &
      `Weight Gain_kg` < quantile(`Weight Gain_kg`, 0.75, na.rm = TRUE) + 1.5 * IQR(`Weight Gain_kg`, na.rm = TRUE)
    ) %>%
    ungroup()
  
  return(animal_data)
}

# Filter and remove outliers for all animals
animal_data <- filter_and_remove_outliers(WG)

# Create individual plots for each animal
plot_cattle <- ggplot(animal_data[animal_data$P.Product == "Cattle", ], aes(x = P.Product, y = `Weight Gain_kg`)) +
  geom_boxplot() +
  labs(
    x = "Animal Type",
    y = "Weight Gain (kg/day)"
  ) +
  theme_minimal()

plot_goat <- ggplot(animal_data[animal_data$P.Product == "Goat", ], aes(x = P.Product, y = `Weight Gain_kg`)) +
  geom_boxplot() +
  labs(
    x = "Animal Type",
    y = "Weight Gain (kg/day)"
  ) +
  theme_minimal()

plot_sheep <- ggplot(animal_data[animal_data$P.Product == "Sheep", ], aes(x = P.Product, y = `Weight Gain_kg`)) +
  geom_boxplot() +
  labs(
    x = "Animal Type",
    y = "Weight Gain (kg/day)"
  ) +
  theme_minimal()

# Combine the plots into one image in landscape orientation
combined_plot <- grid.arrange(plot_cattle, plot_goat, plot_sheep, nrow = 1)


# Display the combined plot
print(combined_plot)
#> TableGrob (1 x 3) "arrange": 3 grobs
#>   z     cells    name           grob
#> 1 1 (1-1,1-1) arrange gtable[layout]
#> 2 2 (1-1,2-2) arrange gtable[layout]
#> 3 3 (1-1,3-3) arrange gtable[layout]

Acknowledgment

This work is funded under the CGIAR Livestock & Climate Initiative.

CGIAR Livestock & Climate Initiative Logo