#My "fancy" for loop
for(i in 1:nrow(d)){ #loops through the rows
host <- d$`Bird Species`[i] #finds the host name
host
if (host %in% Species_Lookup$alt.common.name){ #checks to see if it's in the data
y <- which(Species_Lookup$alt.common.name==host) #gets an index
y
d$sci.name[i] <- Species_Lookup$scientific.name[y] #replaces it with a species
d$sci.name[i]
}
}Introducing SpeciesClassifyR
A bird by any other name is still just a feathered
Let me give you a couple of scenarios.
If I said I saw a mallard the other day you would probably think of this little gal.
But would you know her latin name? Maybe not off the top of your head. (proud #birdnerds excluded)
Now if I said I save a Gavia immer while on a kayake last weekend you might not know I was talking about this beautiful friend (again proud #birdnerds excluded). It is highly recommended to click on these images to see them on a large scale.
I run into this problem alot where I am either dealing with a birds common name and I need its latin name or the inverse.
So often do I run into this that I had to make a lookup table to make finding and often replacing one name for another easier. It looked something like this for loop:
But alas I was forced to copy and paste this for loop whenever I wanted to use it. Nice but not efficient.
Well one day I decided to take this for loop one step further and made a series of functions that allow me to do this with ease! No more copy and pasting from various different projects it all lives in one handy package…..
Enter SpeciesClassifyR
I am proud to present the SpeciesClassifyR package, who’s sole goal is to reduce the headache of dealing with species names.
You can install this package and use the functions inside of it yourself using the below code.
#Install it from Github
pacman::p_install_gh("Jonathan-Dain-42/SpeciesClassifyR")
#Load it in your R session
library(SpeciesClassifyR)The rest of this blog post walks through a few different examples of how to use this package.
Lets say you have a series of avian common names that you want to make latin names. You could run something like this!
# Let's load some test data from the package
data("test_dat")
#Take a look at it. See how the "Species column" has our common names in it.
head(test_dat) |> knitr::kable() | Species | Location | Collection_Date |
|---|---|---|
| blue-winged teal | texas | 2022-09-01 |
| turkey | minnesota | 2022-04-19 |
| turkey | minnesota | 2022-04-19 |
| blue-winged teal | texas | 2022-10-01 |
| chicken | north_dakota | 2022-04-19 |
| blue-winged teal | minnesota | 2022-09-15 |
# use those common names to get scientific names!
classify_species.common(data=test_dat,species_col="Species") |> head() |> knitr::kable()| Species | Location | Collection_Date | family | order | scientific.name |
|---|---|---|---|---|---|
| blue-winged teal | texas | 2022-09-01 | anatidae (ducks, geese, and waterfowl) | anseriformes | spatula discors |
| turkey | minnesota | 2022-04-19 | phasianidae (pheasants, grouse, and allies) | galliformes | meleagris gallopavo |
| turkey | minnesota | 2022-04-19 | phasianidae (pheasants, grouse, and allies) | galliformes | meleagris gallopavo |
| blue-winged teal | texas | 2022-10-01 | anatidae (ducks, geese, and waterfowl) | anseriformes | spatula discors |
| chicken | north_dakota | 2022-04-19 | phasianidae (pheasants, grouse, and allies) | galliformes | gallus gallus |
| blue-winged teal | minnesota | 2022-09-15 | anatidae (ducks, geese, and waterfowl) | anseriformes | spatula discors |
This of course returns a tibble with our newly added latin names as well as some bonus taxonomic data like family and order. One thing to note is that you need to specify the column your common names are in. This allows it to find the proper latin names to give you.
Well this is all fine and good but what if you have a bird species that is somehow lacking from my dataset. That is totally possible! Especially given that when I built this package I had a very North American centered dataset. Never fear you can actually update the dataset yourself.
Something like this:
# Let's say you needed to add common loon to your lookup sheet.
# you would need to in this case since it's already there but just for fun
update_lookup(common.name = "common loon 2", #Just so we can see it.
type = "seabird", # a management type
scientific.name = "gavia immer", # the latin name
english.name.ebird = "common loon", #the proper english name
order = "gaviiformes", # the taxonomic order
family = "gaviidae (loons)", # the taxonomic family
domestic = "wild") |> # whether this bird is wild or domestic
tail()|> knitr::kable() # I piped it to tail just so we can see our new row. | alt.common.name | type | scientific.name | enlish.name.ebird | order | family | domestic |
|---|---|---|---|---|---|---|
| swainsons hawk | raptor/owl/falcon | buteo swainsoni | swainson’s hawk | accipitriformes | accipitridae (hawks, eagles, and kites) | wild |
| eurasian collared dove | other | streptopelia decaocto | eurasian collard dove | columbiformes | columbidae (pigeons and doves) | wild |
| summer tanager | songbird | piranga rubra | summer tanager | passeriformes | cardinalidae (cardinals and allies) | wild |
| northen pintail | seaduck | anas acuta | northern pintail | anseriformes | anatidae (ducks, geese, and waterfowl) | wild |
| warbler (unidentified) | songbird | warbler spp | na | unidentified | unidentified | wild |
| common loon 2 | seabird | gavia immer | common loon | gaviiformes | gaviidae (loons) | wild |
For the above it is important to note that the lookup tibble is formatted with the following columns: alt.common.name, type, scientific.name, ebird.english.name, family, order, domestic. Where domestic is a either wild or domestic.
If those any of these categories are not useful to you fill them with NA’s :)
Finally we can also go from scientific names to common names if we needed to. Maybe for swapping out the tip labels on a phylogenetic tree perhaps (hint hint).
#First lets use our other function to get some scientific names
classify_species.common(data=test_dat,species_col="Species") -> new_dat
#Now we can use this new function to go back to common names
classify_species.scientific(data=new_dat, species_col="scientific.name") |> head()|> knitr::kable()| Species | Location | Collection_Date | family | order | scientific.name | common.name |
|---|---|---|---|---|---|---|
| blue-winged teal | texas | 2022-09-01 | anatidae (ducks, geese, and waterfowl) | anseriformes | spatula discors | blue-winged teal |
| turkey | minnesota | 2022-04-19 | phasianidae (pheasants, grouse, and allies) | galliformes | meleagris gallopavo | wild turkey |
| turkey | minnesota | 2022-04-19 | phasianidae (pheasants, grouse, and allies) | galliformes | meleagris gallopavo | wild turkey |
| blue-winged teal | texas | 2022-10-01 | anatidae (ducks, geese, and waterfowl) | anseriformes | spatula discors | blue-winged teal |
| chicken | north_dakota | 2022-04-19 | phasianidae (pheasants, grouse, and allies) | galliformes | gallus gallus | red junglefowl |
| blue-winged teal | minnesota | 2022-09-15 | anatidae (ducks, geese, and waterfowl) | anseriformes | spatula discors | blue-winged teal |
The final function of this package has nothing to do with classification. It is a helper function that makes calculating the run time of a BEAST MCMC run way easier. That said for the sake of documenting it here you can see an example below.
days_to_run(total_steps = 200000000,hours_per_million = 0.49)[1] "Hello there! Your BEAST run should finish in 4.083 days."
Thats it! A whole package developed by yours truly and released on my Birthday woohoo!! I hope this has been fun or at the very least interesting. If you wanted to learn about making your own R packages you can find more information in Hadley Wickham and Jennifer Bryan’s book “R Packages”.
Untill next time keep your eyes to the sky!
Cheers,
Jonathan Dain




