Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Toady, I encountered a problem while trying to classify certain data.

I have the coordinates of six points.

data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745, 0.171579},
 {0.0847783, 0.277227}, {0.198453, 0.40206}, {0.941614, 0.347187}};

I want to perform some operation on the x coordinate. The operation is as follows. If the x coordinate in one of the following ranges

{{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 0.603909}, 
 {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 0.959049}}

The new x coordinate will have the value 1, 2, 3, 4, 5, 6 respectively.

I tried the following:

judge = {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 0.603909}, 
   {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 0.959049}};
Which[Sequence @@ 
       Flatten@Table[{judge[[i, 1]] < # < judge[[i, 2]] &, i}, {i, 1, 6}]] /@
 data[[All, 1]]

However, it failed. I discovered the mistake was

Table[{judge[[i, 1]] < # < judge[[i, 2]] &, i}, {i, 1, 6}]

I got

{{judge[[i, 1]] < #1 < judge[[i, 2]] &, 1}, 
 {judge[[i, 1]] < #1 < judge[[i, 2]] &, 2},
 {judge[[i, 1]] < #1 < judge[[i, 2]] &, 3},
 {judge[[i, 1]] < #1 < judge[[i, 2]] &, 4},
 {judge[[i, 1]] < #1 < judge[[i, 2]] &, 5},
 {judge[[i, 1]] < #1 < judge[[i, 2]] &, 6}}

rather than

 {{judge[[1, 1]] < #1 < judge[[1, 2]] &, 1}, 
  {judge[[2, 1]] < #1 < judge[[2, 2]] &, 2},
  {judge[[3, 1]] < #1 < judge[[3, 2]] &, 3},
  {judge[[4, 1]] < #1 < judge[[4, 2]] &, 4},
  {judge[[5, 1]] < #1 < judge[[5, 2]] &, 5},
  {judge[[6, 1]] < #1 < judge[[6, 2]] &, 6}}
share|improve this question
    
Do I understand this correctly: You want to get a list of which range number each of the first entries in the data list belong to? –  rasher Jul 3 at 5:37
    
You could try Evaluate. Or inject a value for i using With. –  Sjoerd C. de Vries Jul 3 at 6:27
add comment

7 Answers 7

If I'm interpreting your question correctly...

data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745, 0.171579}, 
        {0.0847783, 0.277227}, {0.198453, 0.40206}, {0.941614, 0.347187}};

intervals = 
  Interval /@ {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 0.603909},  
               {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 0.959049}};

result=First@Pick[Range@Length@intervals, IntervalMemberQ[intervals, #]] & /@ data[[All, 1]]

(* {3, 4, 5, 1, 2, 6} *)

If you actually want to change the data itself, follow by

data[[All, 1]] += result

If you want to replace the x data, follow instead with

data[[All, 1]] = result
share|improve this answer
    
I think data[[All, 1]] = result is what the OP wants. –  m_goldberg Jul 3 at 12:02
    
Lots of options, but I think your use of Interval is the "right" approach given the OPs intent. –  bobthechemist Jul 3 at 13:27
add comment
data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745, 0.171579}, 
        {0.0847783, .277227},  {0.198453, 0.40206}, {0.941614, 0.347187}};
ints = {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 0.603909}, 
        {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 0.959049}};

{IntegerPart@ InverseFunction[Interpolation[ints[[All, 1]], InterpolationOrder -> 1]]
                                                           @#[[1]], #[[2]]} & /@ data

(*
{{3, 0.380297}, {4, 0.8442}, {5, 0.171579}, {1, 0.277227}, {2,  0.40206}, {6, 0.347187}}
*)
share|improve this answer
    
I spy... two fives... –  rasher Jul 3 at 6:25
    
@rasher Oh, I forgot the InterpolationOrder part. Thanks for checking. –  belisarius Jul 3 at 7:23
add comment
data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745, 
    0.171579}, {0.0847783, 0.277227}, {0.198453, 0.40206}, {0.941614, 0.347187}};
data2 = {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 
    0.603909}, {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 0.959049}};
data3 = Range[6]
f[{x_, y_}] := 
  Evaluate@Piecewise@Transpose@{{#, y} & /@ data3, #1 < x <= #2 & @@@ data2};
f /@ data
share|improve this answer
add comment
indexF = Function[{x}, Piecewise[MapIndexed[{First@#2, #[[1]] <= x <= #[[2]]} &, #]]]&;
h = MapAt[indexF[#2], #1, {All, 1}] &;


data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745,  0.171579},
        {0.0847783, .277227}, {0.198453, 0.40206}, {0.941614, 0.347187}};
ints = {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 0.603909}, 
        {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179,  0.959049}};

h[data, ints]
(*{{3,0.380297},{4,0.8442},{5,0.171579},{1,0.277227},{2,0.40206},{6,0.347187}} *)
share|improve this answer
add comment

Just for variety:

data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745, 
    0.171579}, {0.0847783, 0.277227}, {0.198453, 0.40206}, {0.941614, 
    0.347187}};
int = {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 
    0.603909}, {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 
    0.959049}};

Changing the intervals and sorting data:

ord = Union[Flatten@int];
s = SortBy[data, First];

Deriving (sorted) result:

ans = MapThread[{Total[Map[Function[x, Boole[#1 > x]], ord]], #2} &, 
  Transpose@s]

yields:

{{1, 0.277227}, {2, 0.40206}, {3, 0.380297}, {4, 0.8442}, {5, 
  0.171579}, {6, 0.347187}}

If original order desired:

ans[[Ordering@Ordering[data[[All, 1]]]]]

->

{{3, 0.380297}, {4, 0.8442}, {5, 0.171579}, {1, 0.277227}, {2, 
  0.40206}, {6, 0.347187}}

Generalizing:

fun[list_, i_, p_: 0] := Module[{st, res, a},
  st = SortBy[list, First];
  res = MapThread[{Total[Map[Function[x, Boole[#1 > x]], i]], #2} &, 
    Transpose@st];
  If[p != 0, a = res[[Ordering@Ordering[list[[All, 1]]]]], a = res];
  a
  ]

(default is p=0 sorted, otherwise original).

Test: consider sorting random reals between 0 and 10 for intervals:{{0, 2}, {2, 4}, {4, 6}, {6, 8}, {8, 10}}:

test = RandomReal[{0, 10}, {10, 2}]
Grid[{#1, #2 /. 
     Thread[Range[5] -> Partition[Range[0, 10, 2], 2, 1]], #2} & @@@ 
  Transpose[{test, fun[test, Range[0, 10, 2], 1]}], Frame -> All]

enter image description here

share|improve this answer
add comment

For more variety, using a rule replacement

data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745, 
    0.171579}, {0.0847783, 0.277227}, {0.198453, 0.40206}, {0.941614, 
    0.347187}};
range = {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 
    0.603909}, {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 
    0.959049}};
data[[All, 1]] /. (x_ /; x < #[[2]] -> #[[1]] & /@ 
   Transpose[{Range[1, 6], Last /@ range}])

I sacrifice rigor for compactness here, since the rules will assign x < 0.0423892 -> 1 instead of undefined.

update

Borrowing from @rasher and using Association in v10

#[[1]] -> #[[2]] & /@ Transpose[{Range[1, 6], Interval /@ range}]
assoc = Association[%]
With[{dlist = #}, Keys@Select[assoc, IntervalMemberQ[#, dlist] &]] & /@
   data[[All, 1]] // Flatten
share|improve this answer
add comment

Fixing the OP's original function :-

data = {{0.349661, 0.380297}, {0.858156, 0.8442}, {0.906745, 0.171579},
   {0.0847783, 0.277227}, {0.198453, 0.40206}, {0.941614, 0.347187}};

judge = {{0.0423892, 0.141616}, {0.141616, 0.274057}, {0.274057, 0.603909},
   {0.603909, 0.882451}, {0.882451, 0.924179}, {0.924179, 0.959049}};

Which @@ Flatten@
    Table[{judge[[i, 1]] < # < judge[[i, 2]], i}, {i, 1, 6}] & /@ data[[All, 1]]

{3, 4, 5, 1, 2, 6}

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.