4
$\begingroup$

I want to select the data which the third value of sublist is below certain value. So I tried to use Select function as below, but I'm struggling how to apply it to the deep level of the list.

part = Partition[RandomReal[10, 1500], 3];

threedata = {{part[[1 ;; 3]], part[[4 ;; 5]], part[[11 ;; 16]], part[[17 ;; 21]], part[[22 ;; 23]]}, {part[[24 ;; 25]], part[[26 ;; 30]], part[[31 ;; 40]], {part[[41]]}}, {part[[42 ;; 47]], {part[[48 ;; 51]]}}};

sel[list_, width_] :=
Module[{li = list, threash = width, sharp},
sharp = Select[li, #[[3]] < threash &]
];

The function can be used for the first component of the list as

sel[threedata[[1]][[#]], 3.0] & /@ Range[Length[threedata[[1]]]]

So I can get answer by

answer1={sel[#, 8.0] & /@ threedata[[1]], sel[#, 8.0] & /@ threedata[[2]], sel[#, 8.0] & /@ threedata[[3]]}

But I have two questions.

  1. The function Select can take only the list of "True" and for "False (else)", only blanc list "{}" returns. How can I alter the blank list {} to {0,0,0}?

  2. I want to know how to get the answer directly, not by doing each like

    answer1={sel[#, 8.0] & /@ threedata[[1]], sel[#, 8.0] & /@ threedata[[2]], sel[#, 8.0] & /@ threedata[[3]]} ?

Furthermore, if the nest dimension become larger, such as the dataset below, what should I do?? I always have trouble in applying the function to the deepest position of the nest list.

dataset = {{{part[[100 ;; 105]], part[[108 ;; 109]]}, {part[[110 ;; 120]], part[[150 ;; 155]]}, {{part[[160]]}}}, {{part[[181 ;; 188]], part[[190 ;; 193]], part[[195 ;; 197]]}, {part[[200 ;; 205]], part[[208 ;; 209]]}}, {{part[[300 ;; 304]], part[[310 ;; 312]], part[[344 ;; 350]]}, {{part[[400]]}}}};
$\endgroup$

3 Answers 3

4
$\begingroup$
SeedRandom[0];
part = Partition[RandomReal[10, 1500], 3];
threedata = {{part[[1 ;; 3]], part[[4 ;; 5]], part[[11 ;; 16]], 
              part[[17 ;; 21]], part[[22 ;; 23]]}, {part[[24 ;; 25]], 
              part[[26 ;; 30]], part[[31 ;; 40]], {part[[41]]}}, 
             {part[[42 ;; 47]], {part[[48 ;; 51]]}}};

Use a post-processing step using Replace to substitute each empty list {} with {{0,0,0}} as follows:

 sel[list_, width_] := Module[
    {li = list, threash = width, sharp},
    sharp = Select[li, #[[3]] < threash &];
    Replace[sharp, {} -> {{0, 0, 0}}]
];

Or you can use Pick by setting the default value you want:

sel2[list_, width_, default_] := 
Module[{picked}, 
picked = Pick[list, Map[# < width &, list[[All, 3]]]];
If[picked === {}, {default}, picked]];

sel2[threedata[[1]][[#]], 3.0, {0, 0, 0}] & /@ Range[Length[threedata[[1]]]]

To operate on all items in your list, we can do the following:

sel[list_, width_, default_ : {0, 0, 0}] := 
Module[{li = list, threash = width, sharp}, 
sharp = Select[li, #[[3]] < threash &];
Replace[sharp, {} -> If[ListQ[default], {default}, default]]];

GeneralizedSel[data_, fun_, width_, default_ : {0, 0, 0}] := 
MapIndexed[fun[#1, width, default] &, data, {2}];

GeneralizedSel[threedata, sel, 3.0]

GeneralizedSel[threedata, sel, 3.0, {c, c, c}]
(*Additional example*)
$\endgroup$
5
  • $\begingroup$ Thank you very much for your clear answer. This "sel2" could apply to threedata[[1]], threedata[[2]], threedata[[3]]. (But cannot apply to threedata directly. Maybe threedata[[#1]][[#2]]&{Range[Length[threedata],Range[Length[threedata[[1]]]]}) ??) $\endgroup$
    – rani
    Commented Dec 2 at 3:20
  • $\begingroup$ See the update, please! $\endgroup$ Commented Dec 2 at 4:12
  • 1
    $\begingroup$ Yes! This is really what I wanted to do!!! I'm so grateful to you for your help. Thank you so much. $\endgroup$
    – rani
    Commented Dec 2 at 4:21
  • $\begingroup$ I'm glad to help out! :) $\endgroup$ Commented Dec 2 at 4:24
  • 1
    $\begingroup$ I think you kindly helped me several times. Always very helpful! Thank you so much!! $\endgroup$
    – rani
    Commented Dec 2 at 5:38
5
$\begingroup$
DeleteCases[threedata, v_?VectorQ /; Last@v > 8 , All]

{{{{2.05862, 1.73745, 7.99807}, {4.16381, 5.19845, 
    4.62351}, {0.363633, 6.02325, 5.51299}}, {{0.172151, 8.639, 
    7.94074}}, {{8.05002, 5.33195, 6.77588}, {4.97152, 2.49318, 
    7.75588}, {3.32624, 2.14268, 5.8395}}, {{4.03636, 9.91936, 
    5.43251}, {8.6333, 0.843258, 3.02995}, {2.85289, 6.83784, 
    3.39273}, {6.3253, 7.38468, 6.68948}, {9.24276, 2.2842, 
    3.1261}}, {{6.76657, 1.06989, 3.03189}, {2.80111, 6.32522, 
    1.42089}}}, {{{7.67433, 1.11079, 3.75423}, {8.71102, 7.57485, 
    5.52263}}, {{8.02637, 9.15548, 2.93489}, {6.50277, 5.5808, 
    1.68115}, {2.5554, 4.38691, 4.98222}, {1.27752, 0.635506, 
    4.47703}}, {{7.77761, 4.12167, 1.9813}, {0.895783, 4.88678, 
    2.23834}, {8.95071, 1.11196, 6.33943}, {5.05129, 6.41069, 
    1.522}, {3.03562, 7.13628, 1.35734}, {8.58659, 4.26246, 
    5.87284}, {5.17191, 4.99781, 4.95106}, {4.74979, 7.02255, 
    6.0147}, {3.83883, 9.17562, 6.93196}}, {{0.222706, 7.65972, 
    6.25796}}}, {{{4.05888, 6.57972, 0.539185}, {8.93756, 6.0394, 
    0.894871}, {4.21257, 2.55482, 3.92546}, {7.88392, 8.49128, 
    2.57288}}, {{{2.43306, 7.01529, 2.47457}, {3.84513, 1.51018, 
     6.32793}, {4.83487, 0.0208311, 2.51732}, {8.07365, 4.86425, 
     6.59205}}}}}

Explanations:

A vector is a list that has no other lists in it. Last@v means the last element of each of those vectors no matter at which level these happen to be. In addition, the DeleteCases deletes all these cases while preserving list structure.

If you delete {} lists generated due to another threshold being used, you will be changing the list structure. However, you can do so as follows:

DeleteCases[threedata, v_?VectorQ /; Last@v > 2 , All] /. {} -> 
  Nothing
$\endgroup$
2
  • $\begingroup$ Thank you so much telling me about the simple way to write. Although I couldn't understand the meaning of Last@v and VectorQ, the answer was quickly derived. I found literally ">8" means getting rid of list containing ">8" element. $\endgroup$
    – rani
    Commented Dec 2 at 3:23
  • $\begingroup$ Oh, thank you very much for your kind guidance! It is very convenient Function! So then, for question 1, what should I do to change {} to {0,0,0}? (If we change "Last@v > 8" toLast@v > 2, for example, sublists of {} appear.) $\endgroup$
    – rani
    Commented Dec 2 at 4:15
4
$\begingroup$

To answer your second question, you can map your selector at the appropriate level. I'll also simplify your selector function:

sel2[t_] := Select[#[[3]] < t &];

answer2 = Map[sel2[8.0], threedata, {2}]
(* same as answer1 *)

As for question 1, it's not clear why you'd want to do that. The empty list {} is giving you explicit information that no matches were found. By changing {} to {0,0,0}, you're changing the semantics. Maybe you want to change {} to {{0,0,0}}, which would preserve the semantics of Select but would still seem, to me anyway, to be confusing.

Update

To address the update to your question about having deeper levels, you can also set the levelspec to count from the "bottom". It should work for both threedata and dataset.

Map[sel2[8.0], threedata, {-3}]

Map[sel2[8.0], dataset, {-3}]

But just be aware that if the data has more levels, the result will have more levels. It seems to me that that is what you want, but I'm not entirely sure.

$\endgroup$
1
  • $\begingroup$ Thank you very much for your nice answer. Now I can get the clear answer for question2. Well, I have relatively large number of dataset of scientific experiment. Each experimental condition for each sample have three set of data, and I have to make several plots for them. (For example plot the first two element of sublist, {{2.05862, 1.73745}, {4.16381, 5.19845}, {0.363633, 6.02325}} out of {2.05862, 1.73745, 7.99807}, {4.16381, 5.19845, 4.62351}, {0.363633, 6.02325, 5.51299}}.) So, if the answer contains blank {}, ListPlot says error. If just eliminate the {}, the data size will be changed.. $\endgroup$
    – rani
    Commented Dec 2 at 3:15

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.