5
$\begingroup$

If I have some list of lists of coordinates, i.e.

list={{{0,1},{1,2},{2,3},{3,4}},{{3,2},{2,3},{1,4},{0,5}},{{3,1},{2,2},{2,4},{3,5}}}

how can I count how many of the y coordinates in each of the lists has a value of 2 or greater? E.g. the first list has 3 y coordinates greater than or equal to 2, the second has 4 and the third has 3. I have tried

list1=list[[All, All, 2]]
Count[Map[list1], u_ /; u > 2]

but this isn't correctly separating my data by list.

$\endgroup$
2
  • 3
    $\begingroup$ Try this: Count[#, x_ /; x[[2]] >= 2, 1] & /@ list. $\endgroup$ Commented Mar 15, 2018 at 15:44
  • $\begingroup$ That's great thanks! $\endgroup$
    – JJH
    Commented Mar 15, 2018 at 15:52

7 Answers 7

4
$\begingroup$

Here's one way:

Total[UnitStep[list[[All,All,2]]-2],{2}]

{3, 4, 3}

$\endgroup$
4
$\begingroup$

Here is another version using Count (another one is given in a comment):

Count[{_, _?(GreaterEqualThan[2])}] /@ list

And another one that I also like:

Count[{_, y_ /; y >= 2}] /@ list

Putting the condition close to the variable makes it clear what is happening.

$\endgroup$
2
$\begingroup$
Length@*Select[# >= 2 &] /@ list[[All, All, 2]]

Map[Length@*Select[# >= 2 &]][list[[All, All, 2]]] (* as operator form *)

CountsBy[# >= 2 &] /@ list[[All, All, 2]] // KeyDrop[False] // 
  Values // Flatten

Map[CountsBy[Last@# >= 2 &], list] // KeyDrop[False] // 
  Values // Flatten

Map[Last, list, {2}] // Map[Select[# >= 2 &]] // Map[Length] (* readable *)

list /. {a_?NumberQ, b_?NumberQ} :> b // 
  DeleteCases[#, _?(# < 2 &), 2] & // Map[Length]

(Scan[If[Last@# >= 2, Sow[Last@#], Nothing] &, #] // Reap // Last // 
     First // Length) & /@ list

Result

{3, 4, 3}

$\endgroup$
2
$\begingroup$
Length /@ Replace[list, x_ /; Last[x] < 2 :> Nothing, {2}]

{3, 4, 3}

$\endgroup$
2
$\begingroup$

In a shorter way, using Cases:

Map[Length@Cases[#, {_, y_} /; y >= 2] &]@list
(*Thanks, Eldo!*)

(*{3, 4, 3}*)

Also, an alternative using GroupBy:

Map[Length]@Keys@GroupBy[list, Map[If[#[[2]] >= 2, #[[2]], Nothing] &]]

(*{3, 4, 3}*)
$\endgroup$
2
  • 1
    $\begingroup$ +1 - You can further shorten it since the Level specification is redundant: Length@Cases[#, {_, y_} /; y >= 2] & /@ list $\endgroup$
    – eldo
    Commented Sep 17, 2023 at 17:21
  • $\begingroup$ Thanks for pointing out that important detail, @eldo! :-) $\endgroup$ Commented Sep 17, 2023 at 17:33
2
$\begingroup$

You can use Query with GreaterEqualThan.

With list as in OP

Query[
  Map[Length]
  , Select[GreaterEqualThan[2]@*Last]
  ]@list
{3, 4, 3}

Hope this helps.

$\endgroup$
0
$\begingroup$

Some variations on an already exhaustive list of answers:

Length@Select[#, #[[2]] >= 2 &] & /@ list
 (* {3, 4, 3} *)

CountsBy[#, #[[2]] >= 2 &][True] & /@ list
 (* {3, 4, 3} *)

Count[# - 1, _?Positive] & /@ list[[All, All, 2]]
 (* {3, 4, 3} *)
```
$\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.