measurement error and landmark averaging

229 views
Skip to first unread message

Nick

unread,
Jul 31, 2018, 1:38:39 PM7/31/18
to geomorph R package
Dear geomorph community,

I have landmark data stored as a 3-dimensional array in R, whereby rows = 79 landmark positions (first dimension), columns = XYZ coordinates (second dimension), and landmark configurations for each specimen ranging anywhere from 1 to 4 operators per specimen (third dimension). The dataset comprises 296 specimens. Each specimen represents a different species. Dimensions: 79 x 3 x 1154.

I would like to ensure that all operators placed landmarks per specimen within an acceptable range before taking the average to find the mean shape between users. An example or suggestions would be much appreciated as I've tried to do this in geomorph/R to no avail. Thanks!

Sincerely,
Nick


Mike Collyer

unread,
Jul 31, 2018, 1:47:48 PM7/31/18
to geomorph-...@googlegroups.com
Nick,

If you have a factor of length 1154 with specimen information or operator number, you can use coords.subset to split your data into subsets and perform whatever analysis you like.  For example, subsetting by specimen (make a list with 296 arrays) and applying a function to that list to measure, e.g., a coefficient of variation, would be one thing you could do.

You can follow the example used in the help file for finding group means, just realizing that instead of mshape, you would have to develop your own function to measure “acceptable range”.

Cheers!

Mike

--
You received this message because you are subscribed to the Google Groups "geomorph R package" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-pack...@googlegroups.com.
To post to this group, send email to geomorph-...@googlegroups.com.
Visit this group at https://groups.google.com/group/geomorph-r-package.
To view this discussion on the web, visit https://groups.google.com/d/msgid/geomorph-r-package/fac34991-d2e7-4fe7-ae24-b3fa00a53e55%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Message has been deleted

Mike Collyer

unread,
Aug 1, 2018, 2:50:47 PM8/1/18
to geomorph-...@googlegroups.com
Nick,

This turned out to be an issue with arrayspecs  (actually a base R function used in arrayspecs), which is called by coords.subset, specifically with assigning names to subsetted objects.  I was able to add a patch, and now the update can be found on Github.  Unfortunately, we just launched an updated R version on CRAN, so this patch comes in just a little too late to be current with the CRAN version of R.  You can update your version of geomorph with 

devtools::install_github(“geomorphR/geomorph”, ref = “Stable”)

You might also have to update RRPP, if you have not already installed geomorph, 3.0.7

devtools::install_github(“mlcollyer/RRPP”)

Sorry about the hassle but thanks for discovering the issue!

Best,
Mike

On Aug 1, 2018, at 1:24 PM, Nick <nvin...@gmail.com> wrote:

Many thanks for your response Mike. It sounds like I should subset my landmark data by specimen to make downstream analyses easier before I move forward. I got an error when trying the coords.subset function:

coords <- readRDS("~/Desktop/landmarks.rds")
groups <- read.table("~/Desktop/groups.txt", h=TRUE, sep="\t", stringsAsFactors = TRUE)
new.coords <- coords.subset(A = coords, group = groups$species_id)

Error in dimnames(specimens) <- `*vtmp*` : 'dimnames' must be a list

I attached a data frame with the species_id (Factor w/ 296 levels)  and specimen_id (Factor w/ 1154 levels) and also the 3-D array file with the coordinates in case I did something wrong.

Nick





On Tuesday, July 31, 2018 at 10:47:48 AM UTC-7, Michael Collyer wrote:
Nick,

If you have a factor of length 1154 with specimen information or operator number, you can use coords.subset to split your data into subsets and perform whatever analysis you like.  For example, subsetting by specimen (make a list with 296 arrays) and applying a function to that list to measure, e.g., a coefficient of variation, would be one thing you could do.

You can follow the example used in the help file for finding group means, just realizing that instead of mshape, you would have to develop your own function to measure “acceptable range”.

Cheers!

Mike

On Jul 31, 2018, at 1:38 PM, Nick <nvin...@gmail.com> wrote:

Dear geomorph community,

I have landmark data stored as a 3-dimensional array in R, whereby rows = 79 landmark positions (first dimension), columns = XYZ coordinates (second dimension), and landmark configurations for each specimen ranging anywhere from 1 to 4 operators per specimen (third dimension). The dataset comprises 296 specimens. Each specimen represents a different species. Dimensions: 79 x 3 x 1154.

I would like to ensure that all operators placed landmarks per specimen within an acceptable range before taking the average to find the mean shape between users. An example or suggestions would be much appreciated as I've tried to do this in geomorph/R to no avail. Thanks!

Sincerely,
Nick



--
You received this message because you are subscribed to the Google Groups "geomorph R package" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-package+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "geomorph R package" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-pack...@googlegroups.com.
To post to this group, send email to geomorph-...@googlegroups.com.
Visit this group at https://groups.google.com/group/geomorph-r-package.

For more options, visit https://groups.google.com/d/optout.
<landmarks.rds><groups.txt>

Message has been deleted

Nick

unread,
Aug 4, 2018, 11:44:10 PM8/4/18
to geomorph R package
Is there a way to output coordinates as an array by specimen as opposed to a list using coord.subset?

Nick

On Thursday, August 2, 2018 at 12:48:40 PM UTC-7, Nick wrote:
Thanks, that did the trick!

Before I pass on the average shapes for geometric morphometric analysis, I would like to ensure that all operators placed landmarks within an acceptable range of another. Based on previous work using a similar data set, I want to measure “acceptable range” using Procrustes distance (excluding shapes with greater than a predefined Procrustes distance cutoff). Is there a function in geomorph that will allow me to do this? Advice on how to do that would be greatly appreciated.

Many thanks,
Nick

Mike

Mike Collyer

unread,
Aug 5, 2018, 12:16:36 AM8/5/18
to geomorph R package
Nick,

simplfy2array will attempt to turn a list into an array.  However, I’m not sure what you are requesting.  If you use coords.subset with a factor for specimen, you have a list of arrays of coordinates, by specimen.  If you are asking if you can have arrays within arrays, the answer to that is also yes, provided everything is balanced.  4D, 5D, etc., arrays are possible.  You can create them from a list using the array function.  Good luck making sense of them, though!

Best,
Mike

To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-pack...@googlegroups.com.

To post to this group, send email to geomorph-...@googlegroups.com.
Visit this group at https://groups.google.com/group/geomorph-r-package.
Message has been deleted

Nick

unread,
Aug 5, 2018, 1:28:30 AM8/5/18
to geomorph R package
My apologies for being unclear. For example, after I run coords.subset, the structure of each specimen's coordinates look something like this:

> str(specimen1)
List of 948
 $ : num 58.8
 $ : num 68.2
 $ : num 69.6
 $ : num 69.6
.....

Whereas I would like the coordinates for each specimen to be like this:

> str(specimen1)
 num [1:79, 1:3, 1:4] 58.8 68.2 69.6 69.6 59.1 ...

Thank you,
Nick

Mike

Mike Collyer

unread,
Aug 5, 2018, 6:36:59 AM8/5/18
to geomorph-...@googlegroups.com
I find the str function in R to be kind of clunky.  Sometimes it seems to retain the original properties of objects that have been manipulated.  Within coords.subset, first data are sorted into a data.frame and split by groups.  This produces a list.  Within the list objects (group levels) the data are reformatted into arrays.  Apparently, the str function wants to believe that in the process of reformatting - where lists are created and converted to arrays - that the output retains the properties of lists.  I can assure you that the output is a list of arrays, even if str sees it as a lists of lists.  For example,

> data(pupfish) 
> group <- factor(paste(pupfish$Pop, pupfish$Sex))
> levels(group)
[1] "Marsh F"    "Marsh M"    "Sinkhole F" "Sinkhole M"
> new.coords <- coords.subset(A = pupfish$coords, group = group)
> sapply(new.coords, class)
   Marsh F    Marsh M Sinkhole F Sinkhole M 
   "array"    "array"    "array"    "array" 
> sapply(new.coords, is.array)
   Marsh F    Marsh M Sinkhole F Sinkhole M 
      TRUE       TRUE       TRUE       TRUE 
> str(new.coords$`Marsh M`)
List of 1456
 $ : num -0.0352
 $ : num -0.0361
 $ : num 0.0911

So, R can see that arrays were produced, but str wishes to say they have a different structure.  I don’t know why str does this, but I believe the issue is with the str function rather than coords.subset.

Mike

To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-pack...@googlegroups.com.

To post to this group, send email to geomorph-...@googlegroups.com.
Visit this group at https://groups.google.com/group/geomorph-r-package.

Mike Collyer

unread,
Aug 5, 2018, 7:08:23 AM8/5/18
to geomorph-...@googlegroups.com
As a follow-up, I found a way to manipulate str so that the output has the structure one would expect.  (The problem is that the structure of the data was a data frame, which is both a matrix and a list, but as a list, the properties of a list supersede the properties of a matrix.  Thus when converting data to an array, it did not lose the structure of a list.  I just had to first tell R it is only a matrix.)

I have uploaded the update to Github.  If you reinstall geomorph, you should get the structure you expect; e.g.,

> data(pupfish) 
> group <- factor(paste(pupfish$Pop, pupfish$Sex))
> levels(group)
[1] "Marsh F"    "Marsh M"    "Sinkhole F" "Sinkhole M"
> new.coords <- coords.subset(A = pupfish$coords, group = group)
> str(new.coords$`Marsh F`)
 num [1:56, 1:2, 1:16] -0.0336 -0.0375 0.0995 -0.1754 0.0383 ...
 - attr(*, "dimnames")=List of 3
  ..$ : NULL
  ..$ : NULL
  ..$ : chr [1:16] "1" "2" "3" "4" ...

Mike

Nick

unread,
Aug 5, 2018, 11:19:40 AM8/5/18
to geomorph R package
Many thanks! Reinstalling and running the code again worked like a charm.

Nick
Mike

Mike

To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-package+unsub...@googlegroups.com.

To post to this group, send email to geomorph-...@googlegroups.com.
Visit this group at https://groups.google.com/group/geomorph-r-package.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages