NOTE: I formally made a serious mistake in the first example provided. pointLists[[1]]
had an extra element, and we should have a guarantee that Length[pointLists[[i]]] == Length[indexLists[[i]]]
. I apologize for wasting people's time with this.
I have a list pointLists
of sublists of 2D coordinates, where an N = 3
example looks like this:
pointLists =
{{
{131.048, 243.364}, {131.046, 243.321}, {131.037, 243.357},
{130.931, 243.391}, {130.909, 243.377}}, {{164.911, 244.039}, {164.929, 243.942},
{164.74, 244.083}}, {{98.1685, 239.618}, {98.1913, 239.6}, {98.1528, 239.623}
}};
I also have another list indexLists
(where indexLists[[i]]
corresponds to pointLists[[i]]
) which assigns an integer value $\geq 1$ to each coordinate in each sublist. An example of indexLists
for the above example looks like this:
indexLists = {{1, 2, 3, 5, 6}, {1, 2, 4}, {1, 2, 3}};
What I'd like to calculate here, as quickly as possible, is a list differenceList
where a position k
in differenceList
corresponds to the mean or median difference between coordinates in the same sublist of pointLists
where the first coordinate and the second coordinate have values of k
and (k-1)
in indexLists
. Sometimes, however, there will be no examples in any of pointLists
satisfying this criterion. In this case I'd like to simply set differenceList[[k]] = "NULL"
(or really anything distinct and addressable).
Here's another way of thinking about the question:
Imagine, for example, that we have a bunch of cells growing in different colonies/plates, and their color changes over time. But we can't always measure the change for each colony at every time point, just whenever we can.
Each time we measure a color, we add it on the end of a sublist corresponding to the colony in pointLists
and we time stamp the addition by adding the time to a position at the same index as pointLists
in indexLists
. We then ask... for some time point (e.g. $T = 5$), what's the median change from the previous timepoint (e.g. $T = 4$)?
And now imagine that I unfortunately have no control over this data formatting. I just have a structure like pointLists
and indexLists
to work with from measurement device.
Descriptive Example -
Since the description provided is a little wordy, let's plug through the above example in a step-wise fashion (this is optimized for easy reading, and should in no way constrain any algorithm that can achieve the same result):
(k = 1) We set differenceList[[1]] = {0,0}
to handle this special case.
(k = 2) For k=2
we notice that pointLists[[1]]
, pointLists[[2]]
, and pointLists[[3]]
have coordinates with indexLists
values of $k = 2$ and $1$. We compute the differences as, for the first sublist: {131.046, 243.321} - {131.048, 243.364} = {-0.002, -0.043}
, for the second sublist: {164.929, 243.942} - {164.911, 244.039} = {0.018, -0.097}
, and for the third sublist: {98.1913, 239.6} - {98.1685, 239.618} = {0.0228, -0.018}
. We then set: differenceList[[2]] = Median[{{-0.002, -0.043}, {0.018, -0.097}, {0.0228, -0.018}}] = {0.018, -0.043}
.
(k = 3) For k=3
we notice that pointLists[[1]]
and pointLists[[3]]
have coordinates with indexLists
values of $k = 3$ and $2$ (and that pointLists[[2]]
does NOT have any coordinates satisfying this criterion). We compute the differences as - for the first sublist: {131.037, 243.357} - {131.046, 243.321} = {-0.009, 0.036}
, and for the third sublist: {98.1528, 239.623} - {98.1913, 239.6} = {-0.0385, 0.023}
. We then set: differenceList[[3]] = Median[{{-0.009, 0.036}, {-0.0385, 0.023}}] = {-0.02375, 0.0295}
.
(k = 4) For k=4
we notice that none of the sublists have coordinates with an associated index value of $4$ AND ALSO a coordinate with an associated index value of $3$ in indexLists
, so we set differenceList[[4]] = "NULL"
.
(k = 5) For k=5
we notice that, while pointLists[[1]]
has a coordinate with an index value in indexLists
of $5$, and pointLists[[2]]
has a coordinate with an index value in indexLists
of $4$, two coordinates with indices $4$ and $5$ not present in the same sublist, and there are no other examples where a sublist has both values, so we set differenceList[[5]] = "NULL"
.
(k = 6) For k=6
we notice that pointLists[[1]]
has coordinates with indices $k = 6$ and $k = 5$ in pointLists
, and that this is a lone example, so we set differenceList[[6]] = {130.909, 243.377} - {130.931, 243.391} = {-0.022, -0.014}
.
Done. And our result is:
differenceList =
{{0,0}, {0.018, -0.043}, {-0.02375, 0.0295}, "NULL", "NULL", {-0.022, -0.014}}
Is there a clever way to achieve the same result as above for very large instances of pointLists
(in terms of both the number and length of component sublists)? If it matters, I'd like to optimize for speed and not necessarily memory usage.
Also, since I'd like to be able to rerun the algorithm after updating pointLists
, is there some way to quickly calculate the differenceList
value at specific positions (i.e. for specific values of $k$) without recalculating the entire list?
Let's do one more quick example where we calculate differenceList[[5]]
for new versions of pointLists
and indexLists
.
pointLists = {{{122.534, 191.041}, {122.735, 191.023}, {122.692, 190.999}, {122.742, 191.051}}, {{16.2591, 182.679}, {16.2429, 182.681}, {16.3327, 182.726}, {16.4354, 182.733}, {16.4144, 182.737}, {16.3727, 182.759}, {16.3141, 182.783}, {16.3692, 182.77}, {16.4068, 182.745}, {16.3346, 182.712}}};
indexLists = {{1, 3, 4, 5}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}};
Here's a description of how to to calculate differenceList[[5]]
in the new example:
From pointLists[[1]]
we calculate: {122.742, 191.051} - {122.692, 190.999} = {0.05, 0.052}
. From pointLists[[2]]
we calculate: {16.4144, 182.737} - {16.4354, 182.733} = {-0.021, 0.004}
. And finally, we take the median of those values: differenceList[[5]] = Median[{{0.05, 0.052},{-0.021, 0.004}}] = {0.0145, 0.028}
.
Here, {122.742, 191.051}
& {16.4144, 182.737}
have indices of 5
at the same position in the associated indexLists
. And points {122.692, 190.999}
& {16.4354, 182.733}
have indices of four at the same position in indexLists
. We calculate: {122.742, 191.051} - {122.692, 190.999
} since these values are in the same sublist of pointLists
(pointLists[[1]]
), and {16.4144, 182.737} - {16.4354, 182.733}
are both in pointLists[[2]]
.
So that's how we do k = 5
in the new example.
If {122.742, 191.051}
OR {16.4144, 182.737}
OR both are missing, we'd have differenceList[[5]] = {-0.021, 0.004}
(and differenceList[[5]] = {0.05, 0.052}
if {122.692, 190.999}
OR {16.4354, 182.733}
OR both are missing). If three of those coordinates are missing differenceList[[5]] = "NULL"
.