Motivation

We had seen Cassie Stoddard’s 2017 Science paper on varian in avian egg shape across a huge range of species (Stoddard et al. 2017). She measured anywhere from just a few up to a few hundred eggs from each species using a custon MatLab program from museum pictures. While there are some full clutches measured, all of the analyses are based on species mean values rather than any comparison of multiple eggs produced by the same individual. She ends up concluding that the most variation in egg shape (albeit, not that large a % of variation) is explained by flight distances and time spent flying. The striking figure from the paper is figure 1 that shows the full variation of egg shape in morphospace plotted as the degree of asymmetry (pointiness on one end vs round on the other) vs. ellipticity (elongation). Here is the figure from her paper:


In the figure, each species is one point, but as we were doing cross fosters of eggs in 2019, we were noticing that there seemed to be a huge amount of variation in egg shape between different tree swallows and that it seemed to span a lot of the variation in Cassie’s paper. Just for fun, we started taking photos of each full clutch of eggs from 2019 & 2020 and I got in touch with Cassie to get her eggxtractor MatLab code running. Since our photos have a scale bar, I also measured the length and width at the longest/widest point. I haven’t formally calculated volume from those measurements, but they should be good proxies for overall volume. So now we have measures for a bunch of eggs from the same female in a clutch and also some females with egg shape measurements from multiple years. We can easily look at how much variation there is and how consistent individual females are in the shape of their eggs.

Tree Swallow Egg Data

At this point, I’ve measured egg shape as described above for 940 eggs from 185 nests and 159 different females. While there were experiments in these years, all the treatments took place after incubation had started, so this is essentially just a large observational dataset.

The first thing I wanted to do is just to recreate exactly the plot that is shown above from Cassie’s comparative study. I’ve tried to do that here and have set the x and y limits as close as possible to her plot to make it easy to compare.

d_egg <- read.delim(here::here("1_raw_data/data_by_egg.txt"))

ggplot(data = d_egg, mapping = aes(x = A, y = E)) +
  geom_point(size = 0.7) + xlim(-0.02, 0.505) + ylim(0.07, 0.75) +
  xlab("Asymmetry") + ylab("Ellipticity")

This really matches our intuition from looking at eggs in the field!! There is just a huge amount of variation. The single site egg measures from tree swallows span almost all of the variation seen in Cassie’s paper. This raises a lot of other questions. Are tree swallows unusually variable? Would we see geographic variation in tree swallow populations across latitudes that have different migration distances?

Repeatability Within a Clutch

One other question we can address right away is repeatability of egg shape within a clutch. In most cases we have 4-8 eggs measured from each clutch. Unfortunately, we don’t have laying order for these eggs, though we could add that in future years.

As a first step, I’m just repeating the figure above but instead of each point being an egg each point will now be a nest mean with error bars along ellipticity and asymmetry. This isn’t strictly a test, but is a good way to visualize how much spread there is within a nest.

  egg_sum <- d_egg %>%
    group_by(uby) %>%
    summarize(asym = mean(A), ellip = mean(E), a_sd = sd(A) / sqrt(n()), e_sd = sd(E) / sqrt(n()))

    ggplot(data = egg_sum, mapping = aes(x = asym, y = ellip)) + 
      geom_point(size = 0.7) + xlim(-0.02, 0.505) + ylim(0.07, 0.75) +
      xlab("Asymmetry") + ylab("Ellipticity") +
      geom_linerange(data = egg_sum, mapping = aes(x = asym, ymin = ellip - a_sd, ymax = ellip + a_sd, width = 0.1)) +
      geom_linerange(data = egg_sum, mapping = aes(y = ellip, xmin = asym - e_sd, xmax = asym + e_sd, width = 0.1))

Averaging across the clutch does reduce some of the overall spread of egg shape from those really unusual eggs that were far out, but there is still a pretty big cloud of egg shapes that covers the species means for many species on Cassie’s list. You can also see from the error bars (+/- SE) that there is definitely some grouping of nests, though there is so much overlap in the middle that it’s hard to tell the nests apart visually.

Next I’m just running repeatability tests using the rptR package separately for asymmetry, ellipticity, width, and length (Stoffel, Nakagawa, and Schielzeth 2017). I’m running the unadjusted repeatability models just as a simple start.

Asymmetry: repeatability = 0.47; CI = 0.39 to 0.53; P = 0

Ellipticity: repeatability = 0.59; CI = 0.52 to 0.64; P = 0

Length: repeatability = 0.61; CI = 0.53 to 0.66; P = 0

Width: repeatability = 0.32; CI = 0.24 to 0.38; P = 0

So there is significant repeatability within a clutch for all of the measures. Width has the lowest repeatability, then asymmetry (which presumably is being directly influenced by width). I think this actually kind of matches up with some of the biomechanics of egg deposition that Cassie describes in her paper. There are potentially some interesting things to look at here with respect to skipped laying days or weather/resources available. I might predict from Cassie’s paper that eggs layed after a skip would be wider since theys pend longer in the oviduct.

Repeatability Between Years

Next, I wanted to take a look at nests where the same female had eggs measured in both years. The sample size gets a lot smaller here, but it’s still enough to get an idea of what is going on. I’m first plotting year one vs. year 2 measurements just to get a visual of the correlation, then running repeatability estimates again as above.

d_egg2 <- d_egg[, c("unit_box", "year", "A", "E", "len_IJ", "wid_IJ", "fband")]
egg_wide2 <- d_egg2 %>%
    group_by(fband, year) %>%
    summarize(A = mean(A, na.rm = TRUE), E = mean(E, na.rm = TRUE), 
              len_IJ = mean(len_IJ, na.rm = TRUE), wid_IJ = mean(wid_IJ, na.rm = TRUE),  year = mean(year)) %>%
    pivot_wider(names_from = year, values_from = c(A, E, len_IJ, wid_IJ))

ggplot(egg_wide2, mapping = aes(x = A_2019, y = A_2020)) +
  geom_point(col = "coral3") + xlab("Asymmetry 2019") + ylab("Asymmetry 2020") +
  geom_smooth(method = "lm")

ggplot(egg_wide2, mapping = aes(x = E_2019, y = E_2020)) +
  geom_point(col = "coral3") + xlab("Ellipticity 2019") + ylab("Ellipticity 2020") +
  geom_smooth(method = "lm")

ggplot(egg_wide2, mapping = aes(x = len_IJ_2019, y = len_IJ_2020)) +
  geom_point(col = "coral3") + xlab("Egg Length 2019") + ylab("Egg Length 2020") +
  geom_smooth(method = "lm")

ggplot(egg_wide2, mapping = aes(x = wid_IJ_2019, y = wid_IJ_2020)) +
  geom_point(col = "coral3") + xlab("Egg Width 2019") + ylab("Egg Width 2020") +
  geom_smooth(method = "lm")

These cross year comparisons match up really well with the within-year variability. Basically, asymmetry, ellipticity, and length seem to be very similar even when measured a year apart on a different nest, but egg width is not similar a year later.

Here are the actual repeatability measures for each of them:

Asymmetry: repeatability = 0.57; CI = 0.21 to 0.81; P = 8.110^{-4}

Ellipticity: repeatability = 0.46; CI = 0.04 to 0.75; P = 0.00845

Length: repeatability = 0.66; CI = 0.41 to 0.85; P = 2.810^{-4}

Width: repeatability = 0.41; CI = 0 to 0.74; P = 0.10089

So just like above, asymmetry, ellipticity, and length are reasonably repeatable across years, but width is not. I’m not sure about the p-values here, I think I need to increase and run permutation tests to get more accurate ones but it runs very slowly so focus more on the confidence intervals for now.

Pair Plots

Just as a last section here I wanted to plot the four different egg shape measures against each other, because they obviously are not independent (e.g., all else bing equal, increasing width usually will increase asymmetry).

ggplot(d_egg, mapping = aes(x = A, y = E)) +
  geom_point(col = "coral3", size = .5, alpha = 0.4) + xlab("Asymmetry") + ylab("Ellipticity") +
  geom_smooth(method = "lm")

ggplot(d_egg, mapping = aes(x = A, y = len_IJ)) +
  geom_point(col = "coral3", size = .5, alpha = 0.4) + xlab("Asymmetry") + ylab("Egg Length") +
  geom_smooth(method = "lm")

ggplot(d_egg, mapping = aes(x = A, y = wid_IJ)) +
  geom_point(col = "coral3", size = .5, alpha = 0.4) + xlab("Asymmetry") + ylab("Egg Width") +
  geom_smooth(method = "lm")

ggplot(d_egg, mapping = aes(x = E, y = len_IJ)) +
  geom_point(col = "coral3", size = .5, alpha = 0.4) + xlab("Ellipticity") + ylab("Egg Length") +
  geom_smooth(method = "lm")

ggplot(d_egg, mapping = aes(x = E, y = wid_IJ)) +
  geom_point(col = "coral3", size = .5, alpha = 0.4) + xlab("Ellipticity") + ylab("Egg Width") +
  geom_smooth(method = "lm")

ggplot(d_egg, mapping = aes(x = len_IJ, y = wid_IJ)) +
  geom_point(col = "coral3", size = .5, alpha = 0.4) + xlab("Egg Length") + ylab("Egg Width") +
  geom_smooth(method = "lm")

Adding in Geography

There are lots of different things that we could look at with these data just in Ithaca, but it seems like one really promising way forward would be to look at egg shape variation within and between populations from across the tree swallow range or between the different close relatives. Using the GOLO pictures would be awesome for this.

  • Do they have some kind of a scale bar in the photo? If not they can still be used to measure ellipticity and asymmetry but not length and width (though if the distance to camera is always exactly the same maybe it could still be measured).

R Session Info

Here I’m just printing the version of R and packages that I used in this analysis for the sake of reproducibility.

sessionInfo()
## R version 4.0.2 (2020-06-22)
## Platform: x86_64-apple-darwin17.0 (64-bit)
## Running under: macOS Catalina 10.15.6
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] rptR_0.9.22     forcats_0.5.0   stringr_1.4.0   dplyr_1.0.2    
##  [5] purrr_0.3.4     readr_1.3.1     tidyr_1.1.2     tibble_3.0.3   
##  [9] ggplot2_3.3.2   tidyverse_1.3.0
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.5       lubridate_1.7.9  here_0.1         lattice_0.20-41 
##  [5] assertthat_0.2.1 rprojroot_1.3-2  digest_0.6.25    R6_2.4.1        
##  [9] cellranger_1.1.0 backports_1.1.10 reprex_0.3.0     evaluate_0.14   
## [13] httr_1.4.2       pillar_1.4.6     rlang_0.4.7      readxl_1.3.1    
## [17] minqa_1.2.4      rstudioapi_0.11  nloptr_1.2.2.2   blob_1.2.1      
## [21] Matrix_1.2-18    rmarkdown_2.3    labeling_0.3     splines_4.0.2   
## [25] lme4_1.1-23      statmod_1.4.34   munsell_0.5.0    broom_0.7.0     
## [29] compiler_4.0.2   modelr_0.1.8     xfun_0.17        pkgconfig_2.0.3 
## [33] mgcv_1.8-33      htmltools_0.5.0  tidyselect_1.1.0 fansi_0.4.1     
## [37] crayon_1.3.4     dbplyr_1.4.4     withr_2.3.0      MASS_7.3-53     
## [41] grid_4.0.2       nlme_3.1-149     jsonlite_1.7.1   gtable_0.3.0    
## [45] lifecycle_0.2.0  DBI_1.1.0        pacman_0.5.1     magrittr_1.5    
## [49] scales_1.1.1     pbapply_1.4-3    cli_2.0.2        stringi_1.5.3   
## [53] farver_2.0.3     fs_1.5.0         xml2_1.3.2       ellipsis_0.3.1  
## [57] generics_0.0.2   vctrs_0.3.4      boot_1.3-25      tools_4.0.2     
## [61] glue_1.4.2       hms_0.5.3        parallel_4.0.2   yaml_2.2.1      
## [65] colorspace_1.4-1 rvest_0.3.6      knitr_1.30       haven_2.3.1

Bibliography

Stoddard, Mary Caswell, Ee Hou Yong, Derya Akkaynak, Catherine Sheard, Joseph A Tobias, and Lakshminarayanan Mahadevan. 2017. “Avian Egg Shape: Form, Function, and Evolution.” Science 356 (6344): 1249–54.

Stoffel, Martin A, Shinichi Nakagawa, and Holger Schielzeth. 2017. “RptR: Repeatability Estimation and Variance Decomposition by Generalized Linear Mixed-Effects Models.” Methods in Ecology and Evolution 8 (11): 1639–44.