Creating subset using or statement - julia

I have a data frame with 6 columns and thousands of rows containing share transactions. I want to identify rows with bad price data. The following function gives me a subset with the rows with good price data:
function in_price_range(df)
price_good = subset(df, :UnitPrice => X-> (trough_share_price .<= X .<= peak_share_price), skipmissing=true)
return price_good
end
For a subset for bad data I tried:
function out_price_range(df)
price_discrepancy = subset(df, :UnitPrice => X-> (X .< trough_share_price || X .> peak_share_price), skipmissing=true)
return price_discrepancy
end
However, that givers error TypeError: non-boolean (BitVector) used in boolean context
I tried .|| rather than || but that then gives error: syntax: "|" is not a unary operator
How do I fix the code?

In Julia, || is
help?> ||
search: ||
x || y
Short-circuiting boolean OR.
The short-circuiting part meaning, that if x is true, || will not even bother to evaluate y. In other words, this will make a branch in the code. For example:
julia> 5 < 7 || print("This is unreachable")
true
This is great if you want to write code that is efficient for a case like
if something_easy_to_evaluate || something_costly_to_evaluate
# Do something
end
In other words, this is control flow! Obviously, this cannot be broadcasted. For that, what you want is the regular or operator |, which you can broadcast with .|. So for example:
julia> a = rand(3) .< 0.5
3-element BitVector:
1
0
0
julia> b = rand(3) .< 0.5
3-element BitVector:
0
1
0
julia> a .|| b
ERROR: syntax: "|" is not a unary operator
Stacktrace:
[1] top-level scope
# none:1
julia> a .| b
3-element BitVector:
1
1
0
The same applies to && vs &; the former is only used for control-flow, the latter is normal bitwise and.

Related

Ternary operator and range in Julia

I went to this error by chance which I fixed with some diverted way, but still I was curious how it is solved for Julia.
Suppose the MWE:
julia> a = 1 ; b = 5 ; some_logical_value = true
julia> #assert a > 0 ? b in 1:10 : some_logical_value
ERROR: syntax: space required before colon in "?" expression
Stacktrace:
[1] top-level scope at none:1
Which yields an error as, not surprisingly : from ternary operator and : from 1:10 is misleading for Julia. How should we do so?
You just need to add parentheses enclosing the range expression, so either of
#assert a > 0 ? b in (1:10) : some_logical_value
or
#assert a > 0 ? (b in 1:10) : some_logical_value
should work.

How to delete an element from a list in Julia?

v = range(1e10, -1e10, step=-1e8) # velocities [cm/s]
deleteat!(v, findall(x->x==0,v))
I want to delete the value 0 from v. Following this tutorial, I tried deleteat! but I get the error
MethodError: no method matching deleteat!(::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, ::Vector{Int64})
What am I missing here?
Notice the type that is returned by the function range.
typeof(range(1e10, -1e10, step=-1e8))
The above yields to
StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}
Calling the help function for the function deleteat!.
? deleteat!()
deleteat!(a::Vector, inds)
Remove the items at the indices given by inds, and return the > modified a. Subsequent items are shifted to fill the resulting gap.
inds can be either an iterator or a collection of sorted and > unique integer indices, or a boolean vector of the same length as a with true indicating entries to delete.
We can convert the returned type of range using collect. Try the following code.
v = collect(range(1e10, -1e10, step=-1e8))
deleteat!(v,findall(x->x==0,v))
Notice that we can shorten x->x==0 to iszero which yields to
v = collect(range(1e10, -1e10, step=-1e8))
deleteat!(v,findall(iszero,v))
Use filter! or filter:
julia> filter!(!=(0), [1,0,2,0,4])
3-element Vector{Int64}:
1
2
4
In case of a range you can collect it or use:
julia> filter(!=(0), range(2, -2, step=-1))
4-element Vector{Int64}:
2
1
-1
-2
However for big ranges you might just not want to materialize them to save the memory footprint. In that case you could use:
(x for x in range(2, -2, step=-1) if x !== 0)
To see what is being generated you need to collect it:
julia> collect(x for x in range(2, -2, step=-1) if x !== 0)
4-element Vector{Int64}:
2
1
-1
-2

generating expressions and then checking them in Julia

My goal is to be able to generate a list of expressions, p.g., check that a number is in some interval, and then evaluate it.
I was able to do it in the following way.
First, a function genExpr that creates such an Expr:
function genExpr(a::Real, b::Real)::Expr
quote
x < $(a + b) && x > $(a - b)
end
end
Create two expressions:
e1 = genExpr(0,3)
e2 = genExpr(8,2)
Now, my problem is how to pass these expressions to a function along with a number x. Then, this function, checks if such a number satisfies both conditions. I was able to achieve it with the following function:
function applyTest(y::Real, vars::Expr...)::Bool
global x = y
for var in vars
if eval(var)
return true
end
end
return false
end
This works, but the appearance of global suggests the existence of a better way of obtaining the same goal. And that's my question: create a function with arguments a number and a list of Expr's. Such function returns true if any condition is satisfied and false otherwise.
This looks like a you are probably looking into using a macro:
macro genExpr(a::Real, b::Real)
quote
x-> x < $(a + b) && x > $(a - b)
end
end
function applyTest(y::Real, vars::Function...)::Bool
any(var(y) for var in vars)
end
Testing:
julia> e1 = #genExpr(0,3)
#15 (generic function with 1 method)
julia> e2 = #genExpr(8,2)
#17 (generic function with 1 method)
julia> applyTest(0,e1,e2)
true
However, with this simple code a function just generating a lambda would be as good:
function genExpr2(a::Real, b::Real)
return x-> x < (a + b) && x > (a - b)
end

Find indices of non-zero elements from [1,2,0,0,4,0] in julia and create an Arrray with them

I know there is a function that does this, for example:
A = [1,2,0,0,4,0]
find(A)
3-element Array{Int64,1}:
1
2
5
I am trying to do it on my own way, however, I am stuck here
for i=1:endof(A)
if A[i] != 0
[]
end
end
Thanks in advance.
Here's one alternative:
function myfind(c)
a = similar(c, Int)
count = 1
#inbounds for i in eachindex(c)
a[count] = i
count += (c[i] != zero(eltype(c)))
end
return resize!(a, count-1)
end
It actually outperformed find for all the cases I tested, though for the very small example vector you posted, the difference was negligible. There is perhaps some performance advantage to avoiding the branch and dynamically growing the index array.
I have notice that the question is really confusion (because is poorly formulated, sorry about that). Therefore, there are two possible answers: one is [1,2,4]which is an array with the non-zero elements; the other is [1,2,5] which is an array of the indices of the non-zero elements.
Let´s begin with the first option
A = [1,2,0,0,4,0]
B = []
for i=1:endof(A)
if A[i] != 0
push!(B,i)
end
end
println(B)
The output is Any[1,2,5]
However, the type is not the one I wanted. Using typeof(B) it shows Array{Any,1} so I added this code:
B = Array{Int64}(B)
println(B)
typeof(B)
And the result is the desired
[1,2,5]
Array{Int64,1}
To improve its efficiency, following with the recommendations in the comments, I have specified the type of B with the eltype() function before the loop as follows:
A1 = [1,2,0,0,4,0] #The default type is Array{Int64,1}
B1 = eltype(A1)[] #Define the type of the 0 element array B with the type of A
#B1 = eltype(typeof(A))[] this is also valid
for i=1:endof(A1)
if A1[i] != 0
push!(B1::Array{Int64,1},i::Int64)
end
end
println(B1)
typeof(B1)
Then, the output is again the desired
[1,2,5]
Array{Int64,1}
The simplest way of doing this is using the function find(). However, since I´m a beginner, I wanted to do it in another way. However, there is another alternative provided by #DNF that outperform find() for the cases he has tested it (see below answers).
The second option, which creates an output matrix with the non-zero elements has been provided by other users (#Harrison Grodin and #P i) in this discussion.
Thanks all of you for the help!
You have a few options here.
Using the strategy you started with, you can use push! inside the for loop.
julia> B = Int[]
0-element Array{Int64,1}
julia> for element = A
if element != 0
push!(B, element)
end
end
julia> B
3-element Array{Int64,1}:
1
2
4
You can also opt to use short-circuit evaluation.
julia> for element = A
element != 0 && push!(B, element)
end
julia> for element = A
element == 0 || push!(B, element)
end
Both filter and list comprehensions are valid, as well!
julia> B = [element for element = A if element != 0]
3-element Array{Int64,1}:
1
2
4
julia> filter(n -> n != 0, A)
3-element Array{Int64,1}:
1
2
4
Edit: Thanks to the OP's comment, I have realized that the desired result is the indices of the nonzero elements, not the elements themselves. This can be achieved simply with the following. :)
julia> find(A)
3-element Array{Int64,1}:
1
2
5
Just because I don't see a simple solution posted here, this is approach I took to the same problem. I think it is the simplest and most elegant solution. Hope this closes the thread!
julia> A = [1,2,0,0,4,0];
julia> findall(!iszero,A)
3-element Vector{Int64}:
1
2
5

What does "&&" do?

I can't seem to find the resource I need. What does && do in a code that is comparing variables to determine if they are true? If there is a link with a list of the symbol comparisons that would be greatly appreciated.
example: Expresssion 1: r = !z && (x % 2);
In most programming languages that use &&, it's the boolean "and" operator. For example, the pseudocode if (x && y) means "if x is true and y is true."
In the example you gave, it's not clear what language you're using, but
r = !z && (x % 2);
probably means this:
r = (not z) and (x mod 2)
= (z is not true) and (x mod 2 is true)
= (z is not true) and (x mod 2 is not zero)
= (z is not true) and (x is odd)
In most programming languages, the operator && is the logical AND operator. It connects to boolean expressions and returns true only when both sides are true.
Here is an example:
int var1 = 0;
int var2 = 1;
if (var1 == 0 && var2 == 0) {
// This won't get executed.
} else if (var1 == 0 && var2 == 1) {
// This piece will, however.
}
Although var1 == 0 evaluates to true, var2 is not equals to 0. Therefore, because we are using the && operator, the program won't go inside the first block.
Another operator you will see ofter is || representing the OR. It will evaluate true if at least one of the two statements are true. In the code example from above, using the OR operator would look like this:
int var1 = 0;
int var2 = 1;
if (var1 == 0 || var2 == 0) {
// This will get executed.
}
I hope you now understand what these do and how to use them!
PS: Some languages have the same functionality, but are using other keywords. Python, e.g. has the keyword and instead of &&.
It is the logical AND operator
(&&) returns the boolean value true if both operands are true and returns false otherwise.
boolean a=true;
boolean b=true;
if(a && b){
System.out.println("Both are true"); // Both condition are satisfied
}
Output
Both are true
The exact answer to your question depends on the which language your are coding in. In R, the & operator does the AND operation pairwise over two vectors, as in:
c(T,F,T,F) & c(T,T,F,F)
#> TRUE FALSE FALSE FALSE
whereas the && operator operated only on the first element of each vector, as in:
c(T,F,T,F) && c(T,T,F,F)
#> TRUE
The OR operators (| and ||) behave similarly. Different languages will have different meanings for these operators.
In C && works like a logical and, but it only operates on bool types which are true unless they are 0.
In contrast, & is a bitwise and, which returns the bits that are the same.
Ie. 1 && 2 and 1 && 3 are true.
But 1 & 2 is false and 1 & 3 is true.
Let's imagine the situation:
a = 1
b = 2
if a = 1 && b = 2
return "a is 1 and b is 2"
if a = 1 && b = 3
return "a is 1 and b is 3"
In this situation, because a equals 1 AND b = 2, the top if block would return true and "a is 1 and b is 2" would be printed. However, in the second if block, a = 1, but b does not equal 3, so because only one statement is true, the second result would not be printed. && Is the exact same as just saying and, "if a is 1 and b is 1".

Resources