6
$\begingroup$

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}}
$\endgroup$
2
  • $\begingroup$ 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? $\endgroup$
    – ciao
    Jul 3, 2014 at 5:37
  • $\begingroup$ You could try Evaluate. Or inject a value for i using With. $\endgroup$ Jul 3, 2014 at 6:27

7 Answers 7

5
$\begingroup$
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}}
*)
$\endgroup$
2
  • $\begingroup$ I spy... two fives... $\endgroup$
    – ciao
    Jul 3, 2014 at 6:25
  • $\begingroup$ @rasher Oh, I forgot the InterpolationOrder part. Thanks for checking. $\endgroup$ Jul 3, 2014 at 7:23
4
$\begingroup$

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
$\endgroup$
2
  • $\begingroup$ I think data[[All, 1]] = result is what the OP wants. $\endgroup$
    – m_goldberg
    Jul 3, 2014 at 12:02
  • $\begingroup$ Lots of options, but I think your use of Interval is the "right" approach given the OPs intent. $\endgroup$ Jul 3, 2014 at 13:27
1
$\begingroup$
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
$\endgroup$
1
$\begingroup$

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

$\endgroup$
1
$\begingroup$
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}} *)
$\endgroup$
1
  • $\begingroup$ @kguker,Sorry, I can not achieve a result witj your solution, namely, it give some information. $\endgroup$
    – xyz
    Sep 12, 2014 at 7:13
1
$\begingroup$

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}

$\endgroup$
0
$\begingroup$

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
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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