What Constitutes A Charismatic Species and From Whose Perspective?

What Constitutes A Charismatic Species and From Whose Perspective?

Author
Affiliation

Emily McKnight

Carleton University, Ottawa ON, Canada

Modified

April 10, 2026

Figure 1. Photos taken by Malkolm Boothroyd (permission by photographer was granted). A: Caribou calf (Rangifer tarandus) grazing on the Arctic National Wildlife Refuge in Alaska. B: Two red foxes (Vulpes vulpes) engaging in playful behaviour.

Background

Conservation often uses “focal” species as surrogates to help understand or solve complex conservation problems (Ducarme, Luque, and Courchamp 2013). One such example is “charismatic species,” a subjective, loosely defined concept used extensively in policy and scientific literature (Ducarme, Luque, and Courchamp 2013). Charismatic species, often mammalian megafauna (e.g., pandas and polar bears), have been prioritized as icons for conservation funding and are used to garner public and government attention (Ducarme, Luque, and Courchamp 2013). However, there is no clear and well-understood definition of what constitutes a charismatic species. Existing definitions vary from simple adjectives, suggesting charismatic species are “beautiful”, “impressive”, or “dangerous” (Albert, Luque, and Courchamp 2018), to multifaceted descriptions of their usefulness, claiming charismatic species “serve as symbols and rallying points to stimulate conservation awareness and action” (Ducarme, Luque, and Courchamp 2013; Leader-Williams and Dublin 2000). It is thus uncertain how “charisma” might be inferred, what biases fuel its use, and how useful this may be in assisting conservation efforts.

Goal and Objectives

As “charisma” is such a subjective concept, the goal of this exploratory data analysis (EDA) is to get an initial idea of author bias via the locale of the primary author’s institution, the time frame in which its most commonly used, and the species that are receiving this term most often.

  1. Determine which countries the publications are most often from based on the primary author’s affiliation.

  2. Determine common publication years as science and perspective changes over time.

  3. Determine which species are referred to as charismatic most often.

The Data

This data is part of my systematic review for the first chapter of my thesis. I searched Proquest Dissertations and Theses Global, the United Nations Digital Library, Web of Science, and Scopus using the search string “charism* AND species”. Databases were initially searched in August of 2025, but have been repeatedly updated, with the most recent search conducted on March 31, 2026. This code will use the most recent search result data.

I slightly pre-cleaned the four distinct CSV files so I could merge them into one, accounting for inter-database variation in variable names, syntax, and formatting. I also removed any columns that would not contain data useful for this analysis. For example, I removed Volume, Issue, StartPage, EndPage, PageRange, ISSN, EISSN, ISBN, and Language columns from the proquest dataset.

The dataset we will use for this exploratory data analysis is the merged data and contains the following variables:

Variable Description
Title The title of the article
Authors The name of the author(s) of the article
Source The journal or source name
PubDate The publication date in POSIXct format
Year The alpha year of the publication date
DOI The DOI of the publication
Affiliations The institutional affiliations of the authors
Abstract The article’s abstract
Keywords The keywords provided by the authors, journal, etc.
Origin A created variable to identify the database of origin of the article (i.e. proquest, web of science, UN digital library, or scopus)

Part I - Checking Expectations

Title

I would expect the titles to have no NA values, no duplicates, and consistent syntax - no spaces around special characters, no unexpected characters or placements, and consistent capitalization.

combo %>%
  group_by(Title) %>%
  filter(n() > 1) %>%
  ungroup() %>%
  arrange(Title) %>%
  slice_head(n = 10) %>%
  paged_table()

We can see that there are definitely duplicates - there are 1042 duplicate titles in the dataset. However, titles aren’t the most reliable way to determine duplicates as some could repeat. We’ll rely more on DOI duplication as that’s fully unique…more on that later.

Authors

I expect the author names to be formatted as Last Name, Initial(s). I don’t expect separation by a comma because this is a CSV, and that would make the file assume those are each separate cells. I also expect no strange symbols and no NA values.

#This regex is Unicode-aware, meaning accented names will match to ensure international names are included.
combo %>%
  mutate(check = str_detect(Authors, "^([[:alpha:]'-]+, [A-Z]\\.( [A-Z]\\.)*)((; [[:alpha:]'-]+, [A-Z]\\.( [A-Z]\\.)*)*)$")) %>%
  count(check)
# A tibble: 3 × 2
  check     n
  <lgl> <int>
1 FALSE  3219
2 TRUE    444
3 NA        4

Only 444 entries match our desired format. We’ll need to fix that!

We also have 4 NAs…lets take a look.

combo %>%
  filter(is.na(Authors)) %>%
  paged_table()

So our 4 NAs are from 2 corrigendums to other papers, 1 is on the theory of leadership (not relevant to our topic), and the last is the publisher summary to a chapter of a book. We’ll need to remove those.

Source

I expect the source titles to be have consistent syntax and no spelling errors. Lets check.

combo %>%
  select(Source) %>%
  arrange(Source) %>%
  slice(1:10)
# A tibble: 10 × 1
   Source                                                                       
   <chr>                                                                        
 1 2022 IEEE INTERNATIONAL WORKSHOP ON METROLOGY FOR THE SEA LEARNING TO MEASUR…
 2 ACTA ENTOMOLOGICA MUSEI NATIONALIS PRAGAE                                    
 3 ACTA GEOGRAPHICA SLOVENICA-GEOGRAFSKI ZBORNIK                                
 4 ACTA OECOLOGICA-INTERNATIONAL JOURNAL OF ECOLOGY                             
 5 ACTA OECOLOGICA-INTERNATIONAL JOURNAL OF ECOLOGY                             
 6 ACTA OECOLOGICA-INTERNATIONAL JOURNAL OF ECOLOGY                             
 7 ACTA OECOLOGICA-INTERNATIONAL JOURNAL OF ECOLOGY                             
 8 ACTA ORNITHOLOGICA                                                           
 9 ADVANCES IN FRESHWATER DECAPOD SYSTEMATICS AND BIOLOGY                       
10 ADVANCES IN MARINE BIOLOGY, VOL 88                                           

With a quick scan I can see that there are duplicates being treated as separate values due to syntax. E.g., Acta Ornithologica and ACTA ORNITHOLOGICA are viewed as 2 separate journals. We can fix that by making the capitalization consistent!

Publication Date (PubDate)

I expect all publication dates to be in YYYY-MM-DD format and fall within a plausible range. This is likely as early as the 1960s/70s to as recent as 2026.

head(unique(combo$PubDate))
[1] "2012-01-01 UTC" "2023-01-01 UTC" "2024-01-01 UTC" "2021-01-01 UTC"
[5] "2014-01-01 UTC" "2022-01-01 UTC"
range(combo$PubDate, na.rm = TRUE)
[1] "1975-10-30 UTC" "2026-03-01 UTC"

All publication dates are in the expected format. The starting publication date is 1975-10-30 and the most recent is 2026-03-01. This is all within the expected range.

Year

I expect all entries to be numeric containing only the year of publication. I would also expect this to fall within the same range as PubDate.

class(combo$Year)
[1] "numeric"
range(combo$Year, na.rm = TRUE)
[1] 1975 2026

The class is numeric and the range is 1975 to 2026, both just as we’d expect!

DOI

I expect the DOI data to contain only the information after the doi.org/, not the beginning of the URL. Also, as DOIs should be entirely unique to a publication, I would expect no duplicates if there are no duplicate publications.

table(duplicated(combo$DOI, incomparables = NA))

FALSE  TRUE 
 2260  1407 

There are 1407 duplicated DOIs, meaning there are 2260 non-duplicates and NA entries. Lets see how many NAs we have!

sum(is.na(combo$DOI))
[1] 444

There are 444 NA values in the DOI column. How many non-NA entries are in the proper format though?

sum(startsWith(combo$DOI, "10"), na.rm = TRUE)
[1] 3220

If there are 3664 entries that are correct or NA, then 3 are not what we expect…

combo[which(!startsWith(combo$DOI, "10")), ]
# A tibble: 3 × 10
  Title     Authors Source PubDate              Year DOI   Affiliations Abstract
  <chr>     <chr>   <chr>  <dttm>              <dbl> <chr> <chr>        <chr>   
1 Understa… Seaman… PQDT … 2021-01-01 00:00:00  2021 http… <NA>         <NA>    
2 Conserva… Edward… PQDT … 2019-01-01 00:00:00  2019 http… <NA>         <NA>    
3 The Ille… Wyatt,… PQDT … 2008-01-01 00:00:00  2008 http… <NA>         <NA>    
# ℹ 2 more variables: Keywords <chr>, Origin <chr>

These are our 3 culprits! We’ll want to remove the beginning “https://doi.org/” to make them align with the rest of the entries.

Affiliations

I expect the affiliations to be a character that contains information on the institution of the author(s), including the institution name, city, and country.

combo %>%
  select(Affiliations) %>%
  slice_sample(n = 10)
# A tibble: 10 × 1
   Affiliations                                                                 
   <chr>                                                                        
 1 Department of Forest Resources Conservation and Ecotourism, IPB University, …
 2 [Snell-Rood, Emilie C.] Univ Minnesota, Dept Ecol Evolut & Behav, St Paul, M…
 3 Institute of Genetics, University of Nottingham, Nottingham, Nottinghamshire…
 4 [Carlson, Colin J.] Univ Calif Berkeley, Dept Environm Sci Policy & Manageme…
 5 [Bosu, Paul P.; Wagner, Michael R.] No Arizona Univ, Sch Forestry, Flagstaff…
 6 [Morgan, E. J.; Kettle, C. J.] ETH, ITES Ecosyst Management, Univ Str 16, CH…
 7 Wildlife Conservation Society, Bogor, Bogor, West Java, Indonesia; Bukit Bar…
 8 Laboratoire Écologie, Systématique et Évolution, Orsay, Ile-de-France, France
 9 Department of Hydrobiology, Pécsi Tudományegyetem, Pecs, Baranya, Hungary; U…
10 Department of Ecology, Universidade Federal do Rio de Janeiro, Rio de Janeir…

Most affiliations seem to provide their city, state/province, and country, and there do not appear to be any stand-out issues.

Abstract

I expect abstracts to be long character strings. I also expect some NAs because not all sources provided abstracts, particularly from the United Nations document system.

any(!is.character(combo$Abstract), na.rm = TRUE)
[1] FALSE
any(is.na(combo$Abstract))
[1] TRUE

There are no values that are a character and there are NA values, so this is consistent with what we would expect.

Keywords

Finally, I expect our keywords to be in character format, with individual keywords separated by semi-colon with consistent capitalization.

table(grepl(";", combo$Keywords))

FALSE  TRUE 
 1473  2194 

There are 2194 correctly formatted keywords using a semi-colon, and 1473 that are not correctly formatted. How many are NAs?

sum(is.na(combo$Keywords))
[1] 1447

Since 1447 of 1473 entries are NA, this suggests that only 26 are not properly formatted.

combo %>%
  filter(!is.na(Keywords) & grepl(";", Keywords) == FALSE)
# A tibble: 26 × 10
   Title    Authors Source PubDate              Year DOI   Affiliations Abstract
   <chr>    <chr>   <chr>  <dttm>              <dbl> <chr> <chr>        <chr>   
 1 GENERAL… UN      UN Di… 1975-10-30 00:00:00  1975 <NA>  <NA>         <NA>    
 2 RECORD … UN      UN Di… 1981-01-01 00:00:00  1981 <NA>  <NA>         <NA>    
 3 GENERAL… UN      UN Di… 1984-01-01 00:00:00  1984 <NA>  <NA>         <NA>    
 4 Letter … UN      UN Di… 1986-07-18 00:00:00  1986 <NA>  <NA>         <NA>    
 5 General… UN      UN Di… 1988-01-01 00:00:00  1988 <NA>  <NA>         <NA>    
 6 PROVISI… UN      UN Di… 1990-01-12 00:00:00  1990 <NA>  <NA>         <NA>    
 7 INTERNA… UN      UN Di… 1992-01-01 00:00:00  1992 <NA>  <NA>         <NA>    
 8 IMPLEME… UN      UN Di… 1996-02-13 00:00:00  1996 <NA>  <NA>         <NA>    
 9 REPORTS… UN      UN Di… 1999-07-05 00:00:00  1999 <NA>  <NA>         <NA>    
10 THE COL… UN      UN Di… 2001-03-01 00:00:00  2001 <NA>  <NA>         <NA>    
# ℹ 16 more rows
# ℹ 2 more variables: Keywords <chr>, Origin <chr>

The entries from the UN digital library are the culprit. We can swap those commas out for semi-colons!

Part II - Correcting Expectations

Let’s first deal with our formatting issues, then we’ll dive into duplicates.

Authors

First and foremost, lets remove those 4 NAs from earlier.

combo <- combo %>%
  filter(!is.na(Authors))

Then, we had huge variations in syntax, so lets normalize the formatting and save it as a new column, authors_clean.

Code
#Create a function that considers one author name at a time:
format_author <- function(name) {
  if (is.na(name) || str_trim(name) == "") return(NA_character_)
  #^ if the name is somehow NA (despite removal) or is blank, return NA
  name <- str_trim(name) #removes extra spaces around the name
  name <- str_remove(name, ",$") #removes trailing commas
    
  if (str_detect(name, "^[^,]+,\\s*([A-Z]\\.)+(\\s*[A-Z]\\.)*$")) {
    return(name)
  } #^ if the name is already in the correct format, do nothing
    
  if (str_detect(name, ",")) { #if there's a comma, assume Last, First
    parts <- str_split(name, ",", simplify = TRUE) #split into last and first
    last <- str_trim(parts[1]) #take the first part of the split as last name
    first <- str_trim(parts[2]) #take the second part of the split as first
  } else { #if the name is actually First Last
    parts <- str_split(name, "\\s+", simplify = TRUE) #split by space
    last <- parts[ncol(parts)] #take the last word
    first <- paste(parts[-ncol(parts)], collapse = " ") #split everything else
    }
    
  first <- str_replace_all(first, "\\.", "") #remove decimals to add in later
  tokens <- str_split(first, "\\s+")[[1]] 
  tokens <- tokens[tokens != ""] #split first names into letters
    
  initials <- map_chr(tokens, function(tok) { #convert letters to initials
  if (nchar(tok) > 1 && str_detect(tok, "^[A-Z]+$")) { #if 1+ capital letter
      paste0(str_split(tok, "")[[1]], ".", collapse = " ") #add dots between
    } else {
      paste0(str_sub(tok, 1, 1), ".") #take only the first letter and add a dot
    }
  })
    
  paste0(last, ", ", paste(initials, collapse = " ")) #reassemble the pieces
}
  
format_authors_column <- function(author_string) { #apply above function to all
  if(is.na(author_string) || str_trim(author_string) == "") return(NA_character_) #if empty or blank, NA
  authors <- str_split(author_string, ";")[[1]] #split authors by semicolon
  authors <- str_trim(authors)
  authors <- authors[authors != ""] #remove all empty space
    
  authors <- map_chr(authors, format_author) #apply function to each name
    
  paste(authors, collapse = "; ") #combine back by semicolon
}
  
#apply our function to the entire dataset!
combo <- combo %>%
  mutate(authors_clean = map_chr(Authors, format_authors_column))
  
#it made "UN" into "UN, " so let's fix that
combo <- combo %>%
  mutate(authors_clean = case_when(authors_clean == "UN, " ~ "UN",
                                     .default = authors_clean))

  # This isn't perfect, but it's the best I'm able to do. 

Source

Now, we need to convert all of the source titles to title case so we eliminate that syntax issue.

combo$Source <- str_to_title(combo$Source)

DOI

Next, let’s remove the unwanted starting link from our DOIs so all of the entries are in a consistent format.

combo <- combo %>%
  mutate(DOI = str_replace_all(DOI, "https://doi.org/", ""))

Keywords

Finally, let’s replace the commas in our keywords column with semi-colons!

combo$Keywords <- gsub(",\\s*", "; ", combo$Keywords)

Part III - Removing Duplicates

After removing those 4 entries with NAs in the author column, we should be left with 3663 entries. Let’s go ahead and remove any duplicate entries.

Code
combo <- combo %>%
  mutate(yesDOI = !is.na(DOI)) %>% #make a temp column for non-NA DOIs
  group_by(yesDOI) %>% #group by whether rows do or don't have a DOI
  filter(if(yesDOI[1]) {
    !duplicated(DOI) #if there is a DOI, remove duplicates by DOI
  } else {
    !duplicated(Title) #if there is no DOI, remove duplicates by Title
  }
  ) %>%
  ungroup() %>% #ungroup the dataset
  select(-yesDOI) #remove our temp column

We’re now down to 2245 entries. We removed 1418 duplicates!

Now that we’ve removed the bulk, I manually removed any additional duplicates using the revtools package. We’ll now continue on using the dataset cleaned_combo.csv which contains 2194 entries post manual removal.

Part IV - Data Transformation and Wrangling

Now that we have a clean dataset, we need to extract the data out of our columns to address our three key objectives. As a reminder, our first objective is to determine which countries the primary author’s are coming from that are publishing papers utilizing the term “charismatic species”. Our second objective is to determine common publication years to acknowledge how science and perspectives change over time. And finally, our third objective is to determine which species are referred to as charismatic the most often in the literature.

Section A: Extract Country Names

First, we need to create a function that will extract the country names out of the affiliations column. Then, we will apply the function to the dataset, storing the country names in a column called country. Next, we want to normalize any introduced syntax errors, storing the cleaned country results in a column called country_clean.

extract_country <- function(string) {
  if(is.na(string)) return(NA) #if the entry is NA, keep it as NA
  affils <- str_split(string, ";")[[1]] #multiple entries are split by semicolon
  
  #Extract the value at the end of the string, before the comma (aka Country)
  countries <- str_trim(str_extract(affils, "[^,]+$"))
  
  countries <- unique(countries) #pull the unique value
  paste(countries, collapse = "; ") #re-paste together by semicolon
}

# Apply our above function to the data
cleaned_combo <- cleaned_combo %>%
  mutate(country = map_chr(affiliations, extract_country))

# Sometimes the last part of the string wasn't a country, or the countries could have variations in spelling, so we want to normalize this
cleaned_combo <- cleaned_combo %>%
  mutate(country_clean = map_chr(country, function(x) {
    if(is.na(x)) return(NA_character_) #if the data is NA, keep it as NA
    parts <- str_split(x, ";")[[1]] %>% str_trim() #split by semicolon
    
    #compare the name with a regulated dataset of country names
    converted <- countrycode(parts, origin = "country.name",
                             destination = "country.name")
    converted <- unique(na.omit(converted))
    
    #paste the split data back together, separated by semicolon
    paste(converted, collapse = "; ")
  }))

Now, we want to extract only the primary author’s country as that will be used for our key statistic. We will store this data in a column called primary_author_country.

cleaned_combo <- cleaned_combo %>%
  mutate(primary_author_country = str_extract(country_clean, "^[^;]+"))

There are some blanks and NAs in the country column that have data in the affiliations column. Lets manually fill that in!

Code
#first, lets add an ID column so we have a unique row identifier that we can use to ensure our subset data realigns with our main dataset for merging!
cleaned_combo <- cleaned_combo %>%
  mutate(ID = 1:nrow(cleaned_combo))

#now we can subset the data for any blanks or NAs
NA_subset <- subset(cleaned_combo, (is.na(cleaned_combo$country_clean) |
                      cleaned_combo$country_clean == "")
                    & (!is.na(cleaned_combo$affiliations) |
                      cleaned_combo$affiliations == ""))

#manually fill in the countries based on the affiliations
NA_subset <- NA_subset %>%
  mutate(country_clean = case_when(
    ID == "2089" ~ "Brazil", ID == "2093" ~ "Germany", ID == "2094" ~
      "United States", ID == "2095" ~ "Brazil", ID == "2097" ~
      "Switzerland; South Africa; Czechia", ID == "2098" ~ "United States",
    ID == "2100" ~ "Belgium", ID == "2102" ~
      "Germany; Romania; United States; Sweden", ID == "2103" ~ "United States",
    ID == "2104" ~ "Brazil", ID == "2105" ~ "Belgium", ID == "2108" ~
      "United States", ID == "2110" ~ "Canada", ID == "2111" ~ "Australia",
    ID == "2113" ~ "Croatia; Italy", ID == "2115" ~ "Finland; United Kingdom",
    ID == "2116" ~ "Hungary; United States", ID == "2120" ~ "United Kingdom",
    ID == "2121" ~ "Germany", ID == "2122" ~ "United States", ID == "2124" ~
      "Netherlands; Switzerland; Czechia", ID == "2125" ~ "Argentina",
    ID == "2128" ~ "United States", ID == "2131" ~ "Argentina", ID == "2132" ~
      "Germany; Spain", ID == "2133" ~ "Italy", ID == "2136" ~ "Canada",
    ID == "2137" ~ "United States", ID == "2139" ~ "Italy", ID == "2140" ~
      "United States", ID == "2143" ~ "Romania", ID == "2144" ~ "Norway",
    ID == "2146" ~ "United Kingdom", ID == "2147" ~ "United States",
    ID == "2148" ~ "Portugal; United Kingdom", ID == "2151" ~ "United Kingdom",
    ID == "2152" ~ "Canada", ID == "2153" ~ "Germany; Australia", ID == "2155" ~
      "Finland", ID == "2156" ~ "Australia", ID == "2157" ~
      "United States; Saudi Arabia; Thailand", ID == "2158" ~ "United States",
    ID == "2159" ~ "Australia; United Kingdom", ID == "2160" ~ "United States",
    ID == "2161" ~ "United States", ID == "2162" ~ "United States", ID == "2163"
    ~ "Portugal", ID == "2166" ~ "Chile", ID == "2167" ~ "United Kingdom",
    ID == "2168" ~ "Croatia; Australia", ID == "2169" ~ "Portugal", ID == "2170"
    ~ "Israel", ID == "2171" ~ "Italy", ID == "2172" ~
      "Germany; United Kingdom; United States", ID == "2173" ~ "Finland",
    ID == "2176" ~ "China; United Kingdom; United States", ID == "2177" ~ "Israel; United Kingdom", ID == "2178" ~ "Spain", ID == "2180" ~ "United Kingdom; Germany; United States; Cote d'Ivoire; Switzerland; Canada; New Zealand",
    ID == "2182" ~ "Mexico", ID == "2183" ~ "United States", ID == "2184" ~
      "Australia", ID == "2187" ~ "United States", ID == "2188" ~
      "United Kingdom", ID == "2189" ~ "United States", ID == "2191" ~
      "United Kingdom", ID == "2192" ~ "China", ID == "2193" ~ "South Africa",
    .default = NA))

Finally, lets extract the primary author countries from our manually filled in column, and then merge it back into the main dataset!

NA_subset <- NA_subset %>%
  mutate(primary_author_country = str_extract(country_clean, "^[^;]+"))

cleaned_combo <- rows_update(cleaned_combo, NA_subset, by = "ID")

Section B: Determine Country Statistics

Using our extracted primary_author_country, lets count the number and proportion of papers in our dataset that were published per primary author’s country.

#count the number of papers by primary author's country affiliation
primary_country_stats <- cleaned_combo %>%
  group_by(primary_author_country) %>%
  filter(!is.na(primary_author_country)) %>%
  count(sort = TRUE) %>%
  rename(count = n)

#calculate the proportion
primary_country_stats$proportion <- round(
  (primary_country_stats$count/sum(primary_country_stats$count))*100, 1)

Section C: Determine Publication Year Statistics

Similar to above, to tackle objective two we will use our year column to count the number of papers in our dataset published per year.

year_stats <- cleaned_combo %>%
  group_by(year) %>%
  filter(!is.na(year)) %>%
  count(sort = TRUE)

Section D: Extract Species Names

Now, to tackle objective three we want to combine our title and abstract columns so we can extract any species names (including subspecies) that are included in each paper. I created a function called gnfinder_api that parses through the text and compares it to a global species name database using an API. Then, I created a function called common_name that, similar to gnfinder_api, uses an API to compare the scientific names to online databases to extract and store the common names of these species. Finally, I used the classification function from the taxize package to extract the full taxonomic classification for each species.

Each function takes approximately 15-20 minutes to run, though it could take longer depending on the capabilities of your computer. If you’re curious, the code I used is viewable below, but for your convenience I stored the results in a CSV that we will use for our objective three calculations.

Code
# Combine title and abstract text as we want to find the species names mentioned anywhere in either.
#I will be using the variable "df" to start to ensure the country stats info
#and species info don't mess each other up in any way.
df <- cleaned_combo %>%
  mutate(text = paste(title, abstract, sep = " "))

# Create a function that will parse through the text and find globally recognized species names
gnfinder_api <- function(text) {
  res <- POST(
    "https://finder.globalnames.org/api/v1/find",
    body = list(text = text),
    encode = "json"
  )
  
  content <- content(res, as = "text", encoding = "UTF-8")
  parsed <- fromJSON(content, flatten = TRUE)
  
  if (length(parsed$names) == 0) return(NULL)
  
  return(parsed$names)
}

#apply our function to the whole dataset (this takes a few minutes)
results_list <- lapply(df$text, gnfinder_api)

#bind the rows of the list by doc_id so we have a dataframe
names_df <- bind_rows(results_list, .id = "doc_id")

#clean up the dataset to allow for 2 or more words (species and subspecies names), and detect names in Latin format (i.e. Genus species [subspecies]).
species_clean <- names_df %>%
  filter(
    cardinality >= 2,   # allow species + subspecies
    str_detect(name, "^[A-Z][a-z]+\\s[a-z]+")  # Latin-like names
  )

#Pull only the scientific name column so the following process has less excess data slowing it down
species_v <- species_clean$name

#Create a function that provides the common name per scientific name with a system sleep for every 3 requests - this way the session doesn't time out and adheres to proper webscraping etiquette
common_name <- function(sci_name) {
  Sys.sleep(0.35)
  tryCatch(unique(sci2comm(sci_name)), error = function(e) NA)
}

#Apply the function to our scientific names
common_names <- lapply(species_v, common_name)

#Make our list into a dataframe so we can merge it back to our scientific names
CN_df <- as.data.frame(do.call(rbind, common_names))

#Merge the common names with the scientific names
common_names_df <- data.frame(scientific_name = species_v,
                              common_name = CN_df,
                              stringsAsFactors = FALSE)

#It didn't use my provided name for some reason so fix that and also we don't want it to show character(0), it's actually an NA value because there was no found common name.
common_names_df <- common_names_df %>%
  rename(common_name = V1) %>%
  mutate(common_name = map_chr(common_name, ~ if(length(.x) == 0) 
    NA_character_ else .x),
    common_name = str_to_title(common_name)) #make syntax consistent

#Now we want to add on the rest of the taxonomic classifications (about 15 min)
extract_tax <- classification(common_names_df$scientific_name, db = "ncbi",
                         taxize_options(ncbi_sleep = 0.35))

#Use rbind to bind the rows together into a dataframe
fulltax <- rbind(extract_tax)

#It gave me some information I don't want, and this formatting is terrible
#Lets filter out some obvious ones to start
fulltax <- fulltax %>%
  filter(!c(rank == "cellular root" | rank == "subphylum" | rank == "clade" |
              rank == "subclass"))

fulltax <- fulltax %>%
  pivot_wider(id_cols = query, names_from = rank, values_from = name,
              values_fn = first) %>% #we want the taxonomic info as columns
  select(-c(10:28)) %>% #we only want the key taxonomy, lets remove the rest
  rename(scientificName = query) #rename "query" so its clear what the data is

#Now we add on the common names to the full taxonomic dataset
fulltax <- merge(fulltax, common_names_df, by.x = "scientificName", by.y = "scientific_name")

Section E: Determine Charismatic Species Statistics

Finally, let’s count the number of occurrences per species and per taxonomic class.

species_counts <- full_tax %>%
  filter(!is.na(common_name)) %>%
  count(common_name, sort = TRUE)

class_counts <- full_tax %>%
  filter(!is.na(class)) %>%
  count(class, sort = TRUE)

Part V - Data Visualization

Objective 1: Whose charismatic species is it anyway?

Let’s look at the number and proportion of papers that were published based on the primary author’s affiliated country. Based on the table below, we can see that the United States had the highest number of papers using the term charismatic species, with 537 entries representing 28.5% of the data. This was followed by the United Kingdom (n = 223; 11.8%) and Australia (n = 140; 7.4%). Though 87 countries were represented in the data, most countries individually represented under 1%.

Table 1. The number and proportion of articles by primary author country.

Now, let’s see what these statistics look like on a map:

Figure 2. The number of articles using the term “charismatic species” by primary author country.

Objective 2: Publish-or-Perish

Let’s look at the number of papers published per year. As we can see in the figure below, the number of papers using the term “charismatic species” has grown astronomically, reaching a maximum in 2021 (n = 197).

Figure 3. The number of articles using the term “charismatic species” by publication year.

Objective 3: Which species are we calling charismatic?

Let’s take a look at the species that were called “charismatic” the most in the literature. Here we can see that tigers and African elephants were mentioned the most (n = 19), followed by lions (n = 15), wolves (n = 13), koalas (n = 13), and green sea turtles (n = 13).

Figure 4. The species that were called “charismatic” in the literature, sorted by the number of papers that referred to them as such. The data was filtered to include only species mentioned in over 5 articles as over 500 species were mentioned in the literature.

Finally, let’s take a look at the taxonomic classes that these highly charismatic species fall into. As we can see in the figure below, mammals (Mammalia) are referred to as charismatic much more than any other class (n = 541). The next highest classes are birds (Aves; n = 183) and insects (Insecta; n = 180), yet their counts aren’t even close to mammals.

Figure 5. The taxonomic classes that were mentioned as “charismatic” the most in the literature, sorted by the number of papers.

Conclusions

In this preliminary exploratory data analysis, we have taken a peek into the biases in which the term “charismatic species” is being utilized throughout the scientific and grey literature. We can see that Western countries like the United States, United Kingdom, and Australia dominate the literature, utilizing the term “charismatic” the most out of the 87 countries represented in the data. We can also see that the species most often called “charismatic” do not come from these Western countries; it was most often applied to species occupying the Global South - elephants, tigers, and lions. These results suggest a disconnect, as those who are utilizing this terminology and pushing for the conservation of these species do not live in the countries in which the conservation work must be done. They are also applying this term to apex predators, predators of which can kill livestock, pets, and human beings. Despite most papers included in this analysis coming from the 21st century, the majority of which were published in the last 10 years, we are still seeing heavy biases of Western countries controlling the narrative around conservation in the Global South.

References

Albert, Céline, Gloria M. Luque, and Franck Courchamp. 2018. “The Twenty Most Charismatic Species.” PLOS ONE 13 (7): e0199149. https://doi.org/10.1371/journal.pone.0199149.
Ducarme, Frédéric, Gloria M Luque, and Franck Courchamp. 2013. “What Are ‘Charismatic Species’ for Conservation Biologists?”
Leader-Williams, Nigel, and Holly T. Dublin. 2000. “Charismatic Megafauna as ’Flagship Species’.” In Priorities for the Conservation of Mammalian Diversity: Has the Panda Had Its Day?, 53–82. Conservation Biology 3. Cambridge University Press.
Previous
Previous

BIOL 5404W - Urban Trees in Ottawa-Gatineau

Next
Next

BIOL 5404W - Arabidopsis Gene Regulation