Skip to main content

How do I check if any element in a list is positive?


As a simple example of what I would like to do, suppose I have a list a of all real numbers. I would like to perform a simple check to see if some element of a is positive. Of course, I could do this with a simple loop, but I feel as if Mathematica would have a more efficient way of doing this, in the spirit of functional programming. Is there, or do I just have to do this with a clumsy loop:


test=False; For[counter=1;counter<=Length[a];counter++;If[a[[counter]]>0,test=True;];];

Answer



If I understand you correctly, simply test if the maximum value in the list is Positive:



Positive @ Max @ a

Speed comparison with other methods that were posted:


timeAvg = 
Function[func,
Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}],
HoldFirst];

a = RandomInteger[{-1*^7, 2}, 1*^7];


MemberQ[a, _?Positive] // timeAvg

Total@UnitStep[-a] =!= Length@a // timeAvg

Positive@Max@a // timeAvg


0.593


0.0624


0.01148






Early-exit methods


Although very fast, especially with packed lists, the method above does scan the entire list with no possibility for an early exit when a positive elements occurs near the front of the list. In that case a test that does not scan the entire list may be faster, such as the one that R.M posted. Exploring such methods I propose this:


! VectorQ[a, NonPositive]

Unlike MemberQ, VectorQ does not unpack a packed list.


Timings compared to MemberQ and Max, first with an early positive appearance:


SeedRandom[1]
a = RandomReal[{-1*^7, 1000}, 1*^7];


Positive @ Max @ a // timeAvg
! VectorQ[a, NonPositive] // timeAvg
MemberQ[a, _?Positive] // timeAvg


0.008736

0.00013984


0.2528

(Most of the MemberQ time is spent unpacking the list.)


Then no positive appearance (full scan):


a = RandomInteger[{-1*^7, 0}, 1*^7];

Positive @ Max @ a // timeAvg
! VectorQ[a, NonPositive] // timeAvg
MemberQ[a, _?Positive] // timeAvg



0.01148

1.544

2.528

Finally a mid-range appearance of a positive value in an unpacked list:


a = RandomReal[{-50, 0}, 1*^7];
a[[5*^6]] = 1;


Positive @ Max @ a // timeAvg
! VectorQ[a, NonPositive] // timeAvg
MemberQ[a, _?Positive] // timeAvg


0.212

0.702


1.045

Comments

Popular posts from this blog

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1....