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

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
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
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

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
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
    
@kguker,Sorry, I can not achieve a result witj your solution, namely, it give some information. –  Tangshutao Sep 12 at 7:13

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

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

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.