Message Boards Message Boards

0
|
957 Views
|
3 Replies
|
5 Total Likes
View groups...
Share
Share this post:

Get the segment number for a coordinate on measured rod

Posted 6 months ago

Hi, let me try to explain what I want to do, with Wolfram Mathematica, with an example. I have subdivided a 1.7 meter long rod in several segments with offsets

{0., 0.533, 0.617, 0.819, 1.131, 1.455, 1.511, 1.7}

Let me give a position, e.g. x=0.56, I want to know in which segment that x is located. In this case x belong to segment=2.
If I give x=1.15 I should get segment=5.
If I give x=1.61 I should get segment=7.
And so on.
Obviously avoiding loops.
Many thanks for the help

3 Replies

The standard way to do this is with a zero-order interpolation. This is generally optimal for large data sets because it evaluates without a linear search.

ll = {0., 0.533, 0.617, 0.819, 1.131, 1.455, 1.511, 1.7};
func = Interpolation[Transpose[{ll, Range[0, Length[ll] - 1]}], 
   InterpolationOrder -> 0];

Check:

In[358]:= Map[func, {.56, 1.15, 1.61}]

(* Out[358]= {2., 5., 7.} *)

Here is a simple speed test.

vals = Sort[RandomReal[{0, 1}, 10000]];
func = Interpolation[Transpose[{vals, Range[0, Length[vals] - 1]}], 
   InterpolationOrder -> 0];

Timing[Table[Round[func[j]], {j, 0.0, .9, .1}]]

(* Out[354]= {0.000115, {0, 9876, 20109, 29915, 39818, 49888, 60078, 69994, 80163, 90235}} *)

I'm sure I've seen this method in some user forum posts, I just cannot find a reference at the moment.

POSTED BY: Daniel Lichtblau
Posted 6 months ago

I'd probably approach it like this...

data = {0., 0.533, 0.617, 0.819, 1.131, 1.455, 1.511, 1.7};
x = .56;

BlockMap[Between[x, #] &, data, 2, 1]
(* {False, True, False, False, False, False, False} *)

To get the position of True:

FirstPosition[BlockMap[Between[x, #] &, data, 2, 1], True]
(* {2} *)

Take the first element or apply Sequence, if you want a plain integer.

Here's another alternative:

SplitBy[data, LessThan[x]]
(* {{0., 0.533}, {0.617, 0.819, 1.131, 1.455, 1.511, 1.7}} *)

The length of the first list is what you're after:

Length@First@SplitBy[data, LessThan[x]]
(* 2 *)

Probably should consider how to handle edge cases where x is not within any interval or where the data isn't sorted or etc.

POSTED BY: Eric Rimbey

Found! Thanks anyway!

    x := 1.61;
    Count[MapThread[GreaterEqual, {x - Offs, Table[0, Length[Offs]]}], True]
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract