How to fit an ellipse to a series of points in R? - r

I am trying to fit an ellipse to a series of landmark points in R. The data is contained within an array and located at row 6. Here is a sample of the data:
, , Frame001.txt
[,1] [,2]
[1,] 30.13947 -16.92239
[2,] 30.34071 -16.72115
[3,] 30.53260 -16.52926
[4,] 30.72348 -16.33496
[5,] 30.92572 -16.13614
[6,] 31.13358 -15.95087
[7,] 31.34144 -15.76561
[8,] 31.52396 -15.58309
[9,] 31.73182 -15.39782
[10,] 31.95565 -15.21917
[11,] 32.17287 -15.02455
, , Frame002.txt
[,1] [,2]
[1,] 30.13947 -16.92239
[2,] 30.34071 -16.72115
[3,] 30.53260 -16.52926
[4,] 30.72348 -16.33496
[5,] 30.92572 -16.13614
[6,] 31.13358 -15.95087
[7,] 31.34144 -15.76561
[8,] 31.52396 -15.58309
[9,] 31.73182 -15.39782
[10,] 31.95565 -15.21917
[11,] 32.17287 -15.02455
, , Frame003.txt
[,1] [,2]
[1,] 30.13947 -16.92239
[2,] 30.34071 -16.72115
[3,] 30.53260 -16.52926
[4,] 30.72348 -16.33496
[5,] 30.92572 -16.13614
[6,] 31.13358 -15.95087
[7,] 31.34144 -15.76561
[8,] 31.52396 -15.58309
[9,] 31.73182 -15.39782
[10,] 31.95565 -15.21917
[11,] 32.17287 -15.02455
dput(array)
structure(c(30.1394716184822, 30.3407126170086, 30.5325951613319,
30.7234753517486, 30.9257187041817, 31.1335771291367, 31.3414355540918,
31.5239596442118, 31.7318180691669, 31.9556523747537, 32.172869253912,
-16.9223869881883, -16.7211459896618, -16.5292634453385, -16.3349610046196,
-16.1361399024888, -15.950874784594, -15.7656096666993, -15.5830855765793,
-15.3978204586845, -15.2191727672184, -15.0245491951204, 30.1394716184822,
30.3407126170086, 30.5325951613319, 30.7234753517486, 30.9257187041817,
31.1335771291367, 31.3414355540918, 31.5239596442118, 31.7318180691669,
31.9556523747537, 32.172869253912, -16.9223869881883, -16.7211459896618,
-16.5292634453385, -16.3349610046196, -16.1361399024888, -15.950874784594,
-15.7656096666993, -15.5830855765793, -15.3978204586845, -15.2191727672184,
-15.0245491951204, 30.1394716184822, 30.3407126170086, 30.5325951613319,
30.7234753517486, 30.9257187041817, 31.1335771291367, 31.3414355540918,
31.5239596442118, 31.7318180691669, 31.9556523747537, 32.172869253912,
-16.9223869881883, -16.7211459896618, -16.5292634453385, -16.3349610046196,
-16.1361399024888, -15.950874784594, -15.7656096666993, -15.5830855765793,
-15.3978204586845, -15.2191727672184, -15.0245491951204, 30.1394716184822,
30.3407126170086, 30.5325951613319, 30.7234753517486, 30.9257187041817,
31.1335771291367, 31.3414355540918, 31.5239596442118, 31.7318180691669,
31.9556523747537, 32.172869253912, -16.9223869881883, -16.7211459896618,
-16.5292634453385, -16.3349610046196, -16.1361399024888, -15.950874784594,
-15.7656096666993, -15.5830855765793, -15.3978204586845, -15.2191727672184,
-15.0245491951204, 30.2524381537838, 30.3531916700196, 30.5272071629858,
30.7171985365838, 30.8950904282038, 31.0823407740271, 31.2949254546854,
31.4994281378246, 31.7210031127054, 31.9271974411109, 32.1276826397913,
-16.9901669093693, -16.7538535507715, -16.5346514436846, -16.3220667630263,
-16.1441748714063, -15.956924525583, -15.766933151985, -15.5893818716287,
-15.4270311921735, -15.2476277008611, -15.0923291163014), dim = c(11L,
2L, 5L), dimnames = list(NULL, NULL, c("Frame001.txt", "Frame002.txt",
"Frame003.txt", "Frame004.txt", "Frame005.txt")))
I have tried using the ellipse function in R without much success. A similar question on stack exchange used conf_ell but my R isn't liking the Momocs package/can't find the conf_ell function. So the farthest I've got at this point is to create a vector with the desired points...
ellipse.points <- array[6,,]
I want the result to be an ellipse of best fit, using the points contained within the array. Any help would be much appreciated, thankyou!

Related

Calculating the distance between specific rows contained in an array in R

I'm trying to calculate the distance between specific points contained in an array in R. My data looks like this:
curve_array
, , Frame001.txt
[,1] [,2]
[1,] 30.13947 -16.92239
[2,] 30.34071 -16.72115
[3,] 30.53260 -16.52926
[4,] 30.72348 -16.33496
[5,] 30.92572 -16.13614
[6,] 31.13358 -15.95087
[7,] 31.34144 -15.76561
[8,] 31.52396 -15.58309
[9,] 31.73182 -15.39782
[10,] 31.95565 -15.21917
[11,] 32.17287 -15.02455
, , Frame002.txt
[,1] [,2]
[1,] 30.13947 -16.92239
[2,] 30.34071 -16.72115
[3,] 30.53260 -16.52926
[4,] 30.72348 -16.33496
[5,] 30.92572 -16.13614
[6,] 31.13358 -15.95087
[7,] 31.34144 -15.76561
[8,] 31.52396 -15.58309
[9,] 31.73182 -15.39782
[10,] 31.95565 -15.21917
[11,] 32.17287 -15.02455
, , Frame003.txt
[,1] [,2]
[1,] 30.13947 -16.92239
[2,] 30.34071 -16.72115
[3,] 30.53260 -16.52926
[4,] 30.72348 -16.33496
[5,] 30.92572 -16.13614
[6,] 31.13358 -15.95087
[7,] 31.34144 -15.76561
[8,] 31.52396 -15.58309
[9,] 31.73182 -15.39782
[10,] 31.95565 -15.21917
[11,] 32.17287 -15.02455
And for each slice I am trying to calculate the distance between the points contained in row [1,] and row [11,] (the first and last points).
I have truly gotten nowhere with this (I've tried the dist function and the geomorph::interlmkdist function) so any help would be much appreciated. I most recently tried the usedist::dist_subset function but it showed the following error, 'Error in as.matrix(d)[idx, idx] : no 'dimnames' attribute for array'.
I've had success in using the distancePointToPoint function but have to manually input the values from rows [1,] and [11,] which given the extent of the array, is not ideal.
Ideally, I want to return an array that looks something like this:
,, Frame001.txt
[1] 2.781459
,, Frame002.txt
[1] 2.781459
,, Frame003.txt
[1] 2.781459
etc.
Thank you!
dput(curve_array)
structure(c(30.1394716184822, 30.3407126170086, 30.5325951613319,
30.7234753517486, 30.9257187041817, 31.1335771291367, 31.3414355540918,
31.5239596442118, 31.7318180691669, 31.9556523747537, 32.172869253912,
-16.9223869881883, -16.7211459896618, ...), dim = c(11L,
2L, 47L), dimnames = list(NULL, NULL, c("Frame001.txt", "Frame002.txt",
"Frame003.txt", "Frame004.txt", "Frame005.txt", "Frame006.txt",
"Frame007.txt", "Frame008.txt", "Frame009.txt", "Frame010.txt",
"Frame011.txt", "Frame012.txt", "Frame013.txt", "Frame014.txt",
"Frame015.txt", "Frame016.txt", "Frame017.txt", "Frame018.txt",
"Frame019.txt", "Frame020.txt", "Frame021.txt", "Frame022.txt",
"Frame023.txt", "Frame024.txt", "Frame025.txt", "Frame026.txt",
"Frame027.txt", "Frame028.txt", "Frame029.txt", "Frame030.txt",
"Frame031.txt", "Frame032.txt", "Frame033.txt", "Frame034.txt",
"Frame035.txt", "Frame036.txt", "Frame037.txt", "Frame038.txt",
"Frame039.txt", "Frame040.txt", "Frame041.txt", "Frame042.txt",
"Frame043.txt", "Frame044.txt", "Frame045.txt", "Frame046.txt",
"Frame047.txt")))
You can use apply along the third margin to apply the distance operation to each slice of your array. This is just a simple Euclidian distance function between the first and 11th rows. The output is a named vector:
apply(curve_array, 3, function(x) sqrt((x[1, 1]-x[11, 1])^2 + (x[1, 2]-x[11, 2])^2))
#> Frame001.txt Frame002.txt Frame003.txt Frame004.txt Frame005.txt
#> 2.781455 2.781455 2.781455 2.781455 2.668020
#> Frame006.txt Frame007.txt Frame008.txt Frame009.txt Frame010.txt
#> 2.548641 2.350681 2.121847 1.791864 1.446678
#> Frame011.txt Frame012.txt Frame013.txt Frame014.txt Frame015.txt
#> 1.192961 1.054892 1.074074 1.182647 1.403697
#> Frame016.txt Frame017.txt Frame018.txt Frame019.txt Frame020.txt
#> 1.644818 1.889481 2.036533 2.155975 2.240272
#> Frame021.txt Frame022.txt Frame023.txt Frame024.txt Frame025.txt
#> 2.380460 2.484956 2.530551 2.537903 2.557738
#> Frame026.txt Frame027.txt Frame028.txt Frame029.txt Frame030.txt
#> 2.580983 2.659684 2.638101 2.697796 2.698458
#> Frame031.txt Frame032.txt Frame033.txt Frame034.txt Frame035.txt
#> 2.700066 2.693820 2.727060 2.718718 2.631126
#> Frame036.txt Frame037.txt Frame038.txt Frame039.txt Frame040.txt
#> 2.702522 2.744878 2.787322 2.758420 2.801023
#> Frame041.txt Frame042.txt Frame043.txt Frame044.txt Frame045.txt
#> 2.772264 2.772264 2.793633 2.750915 2.686989
#> Frame046.txt Frame047.txt
#> 2.715900 2.665723
With some subsetting apply() works well with dist() too:
apply(curve_array[c(1,11),,], 3, dist)
#> Frame001.txt Frame002.txt Frame003.txt Frame004.txt Frame005.txt Frame006.txt
#> 2.781455 2.781455 2.781455 2.781455 2.668020 2.548641
#> Frame007.txt Frame008.txt Frame009.txt Frame010.txt Frame011.txt Frame012.txt
#> 2.350681 2.121847 1.791864 1.446678 1.192961 1.054892
#> Frame013.txt Frame014.txt Frame015.txt Frame016.txt Frame017.txt Frame018.txt
#> 1.074074 1.182647 1.403697 1.644818 1.889481 2.036533
#> Frame019.txt Frame020.txt Frame021.txt Frame022.txt Frame023.txt Frame024.txt
#> 2.155975 2.240272 2.380460 2.484956 2.530551 2.537903
#> Frame025.txt Frame026.txt Frame027.txt Frame028.txt Frame029.txt Frame030.txt
#> 2.557738 2.580983 2.659684 2.638101 2.697796 2.698458
#> Frame031.txt Frame032.txt Frame033.txt Frame034.txt Frame035.txt Frame036.txt
#> 2.700066 2.693820 2.727060 2.718718 2.631126 2.702522
#> Frame037.txt Frame038.txt Frame039.txt Frame040.txt Frame041.txt Frame042.txt
#> 2.744878 2.787322 2.758420 2.801023 2.772264 2.772264
#> Frame043.txt Frame044.txt Frame045.txt Frame046.txt Frame047.txt
#> 2.793633 2.750915 2.686989 2.715900 2.665723
What do you mean by "distance"? Given your values I am guessing that these are geographic coordinates, and that you want geographic distance on a spheroid, not Euclidean distance.
If so, you could get the distance between the first and 11th row for one matrix like this
library(geosphere)
distGeo(curve_array[1,,1], curve_array[11,,1])
[1] 302457.3
Assuming that the data are in longitude(x)/latitude(y) order, and not the other way around!
And for the whole lot like this
a <- apply(curve_array, 3, \(m) distGeo(m[1,], m[11,]))
head(a)
#Frame001.txt Frame002.txt Frame003.txt Frame004.txt Frame005.txt Frame006.txt
# 302457.3 302457.3 302457.3 302457.3 290466.7 278119.9
For Euclidean distance you could use
b <- apply(curve_array, 3, \(m) dist(m[c(1,11), ]))
head(b)
#Frame001.txt Frame002.txt Frame003.txt Frame004.txt Frame005.txt Frame006.txt
# 2.781455 2.781455 2.781455 2.781455 2.668020 2.548641
Which is the same result as in Allan Cameron's answer

r igraph - how does plot() read the layout matrix?

My question is related to this one here, which unfortunately has not been responded. I'm trying to automatically annotate text next to highlighted communities on a plot. An intermediate step is to understand how nodes are placed on a plot.
G <- make_graph('zachary')
l <- layout_with_fr(G)
l
A layout is a matrix with rows representing nodes and columns representing the x and y plot parameters.
[,1] [,2]
[1,] 2.8510654 -2.2404898
[2,] 2.7183497 -1.1815130
[3,] 3.1429205 0.1117099
[4,] 1.5585372 -1.0743325
[5,] 2.2808632 -4.2035479
[6,] 2.1698198 -5.0526766
[7,] 1.4938068 -4.6975884
[8,] 1.9710816 -1.4672218
[9,] 3.5407035 0.5407852
[10,] 2.2222909 1.9079805
[11,] 3.0784642 -4.5828448
[12,] 4.4115351 -4.1057462
[13,] 0.6002378 -2.2432049
[14,] 2.5010525 -0.1563341
[15,] 4.8914673 4.1417759
[16,] 3.2053338 3.9212694
[17,] 1.1825200 -6.4099021
[18,] 3.7155897 -2.8354432
[19,] 3.8272351 4.2660906
[20,] 3.8636487 -0.5671906
[21,] 2.7302411 3.3998888
[22,] 1.6084374 -2.7407388
[23,] 4.3432855 3.8101278
[24,] 5.9392042 2.2364929
[25,] 6.9980077 0.2389222
[26,] 7.1608499 1.1360134
[27,] 6.0171481 4.0279067
[28,] 5.4996627 1.0367163
[29,] 4.4961257 0.9434659
[30,] 5.5987563 3.2314488
[31,] 2.9958404 1.2022317
[32,] 5.1188900 0.2919268
[33,] 4.1088296 2.5032294
[34,] 4.1686534 2.1339884
But the x, y coordinates of the plot go from -1 to 1, unlike the min-max coordinates in the layout matrix. So how is plot(G, layout = l) reading the layout matrix?
The according to the source, the plot method for objects of class igraph simply rescales the matrix from -1 to 1.
library(igraph)
set.seed(3)
l <- layout_with_fr(G)
[,1] [,2]
[1,] -2.283 0.658
[2,] -1.289 -0.108
[3,] 0.146 1.012
[4,] -1.523 1.601
#... with 30 more rows.
plot(G,layout = l)
maxs <- apply(l, 2, max)
mins <- apply(l, 2, min)
ll <- scale(l, center=(maxs+mins)/2, scale=(maxs-mins)/2)
ll
[,1] [,2]
[1,] -0.2422 -0.1051
[2,] -0.0704 -0.3821
[3,] 0.1775 0.0228
[4,] -0.1108 0.2357
#... with 30 more rows.
plot(G,layout = ll)
Note that the actual rescaling is performed with igraph::norm_coords:
igraph::norm_coords(l)
[,1] [,2]
[1,] -0.2422 -0.1051
[2,] -0.0704 -0.3821
[3,] 0.1775 0.0228
[4,] -0.1108 0.2357
#... with 30 more rows.

How to create a date sequence for 10 years with 16 Day interval with each year starts with 1st January

Following code create a date sequence of 10 years with 16 Day interval.
library(chron)
seq.dates("01/01/2008","12/31/2017", 16)
Output
[1] 01/01/08 01/17/08 02/02/08 02/18/08 03/05/08 03/21/08 04/06/08 04/22/08 05/08/08
[10] 05/24/08 06/09/08 06/25/08 07/11/08 07/27/08 08/12/08 08/28/08 09/13/08 09/29/08
[19] 10/15/08 10/31/08 11/16/08 12/02/08 12/18/08 **01/03/09** 01/19/09 02/04/09 02/20/09
[28] 03/08/09 03/24/09 04/09/09 04/25/09 05/11/09 ..........
........................
...........................
[208] 01/25/17 02/10/17 02/26/17 03/14/17 03/30/17 04/15/17 05/01/17 05/17/17 06/02/17
[217] 06/18/17 07/04/17 07/20/17 08/05/17 08/21/17 09/06/17 09/22/17 10/08/17 10/24/17
[226] 11/09/17 11/25/17 12/11/17 12/27/17
I want first entry for every year to be 1st January not the day which comes after 16 days from the last entry of previous year (BOLD entry in the example sequence) and subsequent entries accordingly.
A long way to do this would be creating date sequence for individual years separately then merging them in a single vector. I'm curious that is there any way to do this in a single line code.
How's this work for you. Uses sapply to pass a vector of starting points and then makes seq.dates do more limited sequences. The sapply function will simplify to an array if possible.
dates(sapply( seq.dates("01/01/2008", "01/01/2017", by="years") ,
function(x) seq.dates(x, to=x+365, by=16, length=23)))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 01/01/08 01/01/09 01/01/10 01/01/11 01/01/12 01/01/13 01/01/14 01/01/15
[2,] 01/17/08 01/17/09 01/17/10 01/17/11 01/17/12 01/17/13 01/17/14 01/17/15
[3,] 02/02/08 02/02/09 02/02/10 02/02/11 02/02/12 02/02/13 02/02/14 02/02/15
[4,] 02/18/08 02/18/09 02/18/10 02/18/11 02/18/12 02/18/13 02/18/14 02/18/15
[5,] 03/05/08 03/06/09 03/06/10 03/06/11 03/05/12 03/06/13 03/06/14 03/06/15
[6,] 03/21/08 03/22/09 03/22/10 03/22/11 03/21/12 03/22/13 03/22/14 03/22/15
[7,] 04/06/08 04/07/09 04/07/10 04/07/11 04/06/12 04/07/13 04/07/14 04/07/15
[8,] 04/22/08 04/23/09 04/23/10 04/23/11 04/22/12 04/23/13 04/23/14 04/23/15
[9,] 05/08/08 05/09/09 05/09/10 05/09/11 05/08/12 05/09/13 05/09/14 05/09/15
[10,] 05/24/08 05/25/09 05/25/10 05/25/11 05/24/12 05/25/13 05/25/14 05/25/15
[11,] 06/09/08 06/10/09 06/10/10 06/10/11 06/09/12 06/10/13 06/10/14 06/10/15
[12,] 06/25/08 06/26/09 06/26/10 06/26/11 06/25/12 06/26/13 06/26/14 06/26/15
[13,] 07/11/08 07/12/09 07/12/10 07/12/11 07/11/12 07/12/13 07/12/14 07/12/15
[14,] 07/27/08 07/28/09 07/28/10 07/28/11 07/27/12 07/28/13 07/28/14 07/28/15
[15,] 08/12/08 08/13/09 08/13/10 08/13/11 08/12/12 08/13/13 08/13/14 08/13/15
[16,] 08/28/08 08/29/09 08/29/10 08/29/11 08/28/12 08/29/13 08/29/14 08/29/15
[17,] 09/13/08 09/14/09 09/14/10 09/14/11 09/13/12 09/14/13 09/14/14 09/14/15
[18,] 09/29/08 09/30/09 09/30/10 09/30/11 09/29/12 09/30/13 09/30/14 09/30/15
[19,] 10/15/08 10/16/09 10/16/10 10/16/11 10/15/12 10/16/13 10/16/14 10/16/15
[20,] 10/31/08 11/01/09 11/01/10 11/01/11 10/31/12 11/01/13 11/01/14 11/01/15
[21,] 11/16/08 11/17/09 11/17/10 11/17/11 11/16/12 11/17/13 11/17/14 11/17/15
[22,] 12/02/08 12/03/09 12/03/10 12/03/11 12/02/12 12/03/13 12/03/14 12/03/15
[23,] 12/18/08 12/19/09 12/19/10 12/19/11 12/18/12 12/19/13 12/19/14 12/19/15
[,9] [,10]
[1,] 01/01/16 01/01/17
[2,] 01/17/16 01/17/17
[3,] 02/02/16 02/02/17
[4,] 02/18/16 02/18/17
[5,] 03/05/16 03/06/17
[6,] 03/21/16 03/22/17
[7,] 04/06/16 04/07/17
[8,] 04/22/16 04/23/17
[9,] 05/08/16 05/09/17
[10,] 05/24/16 05/25/17
[11,] 06/09/16 06/10/17
[12,] 06/25/16 06/26/17
[13,] 07/11/16 07/12/17
[14,] 07/27/16 07/28/17
[15,] 08/12/16 08/13/17
[16,] 08/28/16 08/29/17
[17,] 09/13/16 09/14/17
[18,] 09/29/16 09/30/17
[19,] 10/15/16 10/16/17
[20,] 10/31/16 11/01/17
[21,] 11/16/16 11/17/17
[22,] 12/02/16 12/03/17
[23,] 12/18/16 12/19/17
I was a bit surprised at this result since I thought the value would be a character matrix, but str shows it's a matrix of chron date elements. Can remove the apparent "matrix" (actually "dates" with a dimension attribute) structure with a call to c:
str(c(dates(sapply( seq.dates("01/01/2008", "01/01/2017", by="years") , function(x) seq.dates(x, to=x+365, by=16, length=23))) ))
'dates' num [1:230] 01/01/08 01/17/08 02/02/08 02/18/08 03/05/08 ...
- attr(*, "format")= chr "m/d/y"
- attr(*, "origin")= num [1:3] 1 1 1970

Apply - return results binded by rows not by columns

I have a function which applied on a vector of lenght 5 returns a matrix with 4 rows and 5 columns. Then I want to use apply() in order to call my function again on each row of the results matrix and obtain matrix with 16 (4*4) rows and 5 columns. Unfortuneately apply() combines the results into 4x20 matrix. How is it possible to change that without using lists?
matrixFromVector = function(x){
return(rbind(x*rnorm(1,1,.01),x*rnorm(1,1,.01),x*rnorm(1,1,.1),x*rnorm(1,1,.01))) }
a = matrixFromVector(1:5)
t(a)
[,1] [,2] [,3] [,4]
[1,] 1.008391 1.005974 1.077223 0.9865611
[2,] 2.016782 2.011947 2.154445 1.9731222
[3,] 3.025173 3.017921 3.231668 2.9596833
[4,] 4.033565 4.023894 4.308890 3.9462444
[5,] 5.041956 5.029868 5.386113 4.9328055
After applying my function to each row of a I would like to have
[1,] [2,] [3,] [4,] [5,]
[1,] 1.0242459 2.0484917 3.0727376 4.0969835 5.1212293
[2,] 0.9999314 1.9998629 2.9997943 3.9997257 4.9996572
[3,] 1.0836573 2.1673146 3.2509719 4.3346292 5.4182865
[4,] 1.0005137 2.0010275 3.0015412 4.0020550 5.0025687
[5,] 1.0314108 2.0628216 3.0942323 4.1256431 5.1570539
[6,] 0.9995248 1.9990496 2.9985744 3.9980992 4.9976239
[7,] 1.0908017 2.1816034 3.2724051 4.3632069 5.4540086
[8,] 0.9801833 1.9603667 2.9405500 3.9207333 4.9009166
[9,] 0.9697334 1.9394669 2.9092003 3.8789338 4.8486672
[10,] 0.8484190 1.6968380 2.5452570 3.3936760 4.2420950
[11,] 0.9120351 1.8240703 2.7361054 3.6481405 4.5601756
[12,] 0.9596908 1.9193816 2.8790724 3.8387632 4.7984540
[13,] 1.0226757 2.0453515 3.0680272 4.0907030 5.1133787
[14,] 1.0069771 2.0139543 3.0209314 4.0279085 5.0348857
[15,] 1.0748773 2.1497545 3.2246318 4.2995090 5.3743863
[16,] 0.9841864 1.9683728 2.9525592 3.9367456 4.9209319
Instead I got
apply(a,1,matrixFromVector)
[,1] [,2] [,3] [,4]
[1,] 1.0262524 1.0237143 1.074673 0.9885002
[2,] 0.9990472 1.0189053 1.062644 0.9965570
[3,] 0.9464976 0.8973152 1.138847 0.8639614
[4,] 1.0063561 1.0080947 1.080825 1.0033793
[5,] 2.0525048 2.0474286 2.149346 1.9770004
[6,] 1.9980944 2.0378107 2.125288 1.9931140
[7,] 1.8929952 1.7946303 2.277693 1.7279229
[8,] 2.0127121 2.0161895 2.161650 2.0067587
[9,] 3.0787573 3.0711429 3.224019 2.9655005
[10,] 2.9971416 3.0567160 3.187933 2.9896710
[11,] 2.8394929 2.6919455 3.416540 2.5918843
[12,] 3.0190682 3.0242842 3.242475 3.0101380
[13,] 4.1050097 4.0948572 4.298693 3.9540007
[14,] 3.9961888 4.0756214 4.250577 3.9862280
[15,] 3.7859905 3.5892607 4.555386 3.4558457
[16,] 4.0254242 4.0323789 4.323300 4.0135174
[17,] 5.1312621 5.1185715 5.373366 4.9425009
[18,] 4.9952359 5.0945267 5.313221 4.9827850
[19,] 4.7324881 4.4865759 5.694233 4.3198072
[20,] 5.0317803 5.0404736 5.404125 5.0168967
or
apply(a,1,function(x) t(matrixFromVector(x)))
[,1] [,2] [,3] [,4]
[1,] 1.0242459 0.9999314 1.0836573 1.0005137
[2,] 2.0484917 1.9998629 2.1673146 2.0010275
[3,] 3.0727376 2.9997943 3.2509719 3.0015412
[4,] 4.0969835 3.9997257 4.3346292 4.0020550
[5,] 5.1212293 4.9996572 5.4182865 5.0025687
[6,] 1.0314108 0.9995248 1.0908017 0.9801833
[7,] 2.0628216 1.9990496 2.1816034 1.9603667
[8,] 3.0942323 2.9985744 3.2724051 2.9405500
[9,] 4.1256431 3.9980992 4.3632069 3.9207333
[10,] 5.1570539 4.9976239 5.4540086 4.9009166
[11,] 0.9697334 0.8484190 0.9120351 0.9596908
[12,] 1.9394669 1.6968380 1.8240703 1.9193816
[13,] 2.9092003 2.5452570 2.7361054 2.8790724
[14,] 3.8789338 3.3936760 3.6481405 3.8387632
[15,] 4.8486672 4.2420950 4.5601756 4.7984540
[16,] 1.0226757 1.0069771 1.0748773 0.9841864
[17,] 2.0453515 2.0139543 2.1497545 1.9683728
[18,] 3.0680272 3.0209314 3.2246318 2.9525592
[19,] 4.0907030 4.0279085 4.2995090 3.9367456
[20,] 5.1133787 5.0348857 5.3743863 4.9209319
We can loop over the rows using lapply and then do this
do.call(rbind, lapply(seq_len(nrow(a)), function(i) matrixFromVector(a[i,])))
Or we place the output in a list using apply and then do the rbind
do.call(rbind, do.call(c, apply(a, 1, function(x) list(matrixFromVector(x)))))
why not
apply(t(a), 1, matrixFromVector)
or
apply(a, 2, matrixFromVector)

Extracting element from list of lists in R?

I have a list in the following format:
[[825]][[4]]
Each of the 4 inside list elements are different sized and dimensioned arrays:
[[1]]
[1] 0.02918644 0.03239657 0.03560670 0.03881683 0.04202696 0.04523709 0.04844722 0.05165735
[9] 0.05486748 0.05807761 0.06128774 0.06449787 0.06770800 0.07091813 0.07412827 0.07733840
[17] 0.08054853 0.08375866 0.08696879 0.09017892
[[2]]
[1] 0.7581078 0.7587820 0.7608009 0.7641538 0.7688234 0.7747857 0.7820113 0.7904655 0.8001093
[10] 0.8109003 0.8244816 0.8444896 0.8706241 0.9023530 0.9391094 0.9803280 1.0254709 1.0740433
[19] 1.1256013 1.1797536
[[3]]
[,1] [,2] [,3]
[1,] 0.4177711 0.34606863 2.361603e-01
[2,] 0.4345125 0.35491274 2.105747e-01
[3,] 0.4512540 0.36375685 1.849892e-01
[4,] 0.4679954 0.37260096 1.594036e-01
[5,] 0.4847369 0.38144507 1.338180e-01
[6,] 0.5014783 0.39028918 1.082325e-01
[7,] 0.5182198 0.39913329 8.264693e-02
[8,] 0.5349612 0.40797740 5.706137e-02
[9,] 0.5517027 0.41682150 3.147581e-02
[10,] 0.5684441 0.42566561 5.890257e-03
[11,] 0.6059978 0.39400216 0.000000e+00
[12,] 0.6497759 0.35022414 0.000000e+00
[13,] 0.6935539 0.30644612 0.000000e+00
[14,] 0.7373319 0.26266811 -2.408519e-18
[15,] 0.7811099 0.21889009 -6.394265e-19
[16,] 0.8248879 0.17511207 1.129666e-18
[17,] 0.8686659 0.13133405 2.898758e-18
[18,] 0.9124440 0.08755604 4.667850e-18
[19,] 0.9562220 0.04377802 6.436942e-18
[20,] 1.0000000 0.00000000 0.000000e+00
[[4]]
[,1]
[1,] 0.03849906
[2,] 0.04269549
[3,] 0.04680160
[4,] 0.05079714
[5,] 0.05466400
[6,] 0.05838658
[7,] 0.06195207
[8,] 0.06535055
[9,] 0.06857498
[10,] 0.07162115
[11,] 0.07433489
[12,] 0.07637498
[13,] 0.07776951
[14,] 0.07859245
[15,] 0.07893464
[16,] 0.07889032
[17,] 0.07854784
[18,] 0.07798443
[19,] 0.07726429
[20,] 0.07643877
I want to have 4 new lists, each with 825 elements:
[[4]][[825]]
For example, all the [[1]]'s, [[2]]'s etc. from the list of 825 should be combined.
What's the best way to do this? I've been trying to figure it out with some sort of apply..
First create an example list of lists:
big.lst <- lapply(1:825, function(x) rep(list(rnorm(10)), 4))
#check lengths
length(big.lst)
#[1] 825
unique(lengths(big.lst))
#[1] 4
Then lapply a subset over the big list. I chose 1:4 to create four new groups, but you can genralize with 1:length(big.lst[[1]]) as each sublist has the same length:
newlst <- lapply(1:4, function(x) lapply(big.lst, '[[', x))
#verify answer
length(newlst)
#[1] 4
unique(lengths(newlst))
#[1] 825

Resources