Julia, integer vs boolean results from selection of instances in two arrays - arrays

I've got my 3d array called Pop. I want find out how many times two different conditions are met, and they both work for me independently but I can't put the two together.
Pop[end, :, 1] .== 3
works ok, produces an integer vector of 1's and 0's which is correct. Also
Pop[end-1, :, 1] .== 4
works, again returns integer vector, however when I put the two together as:
count(Pop[end, :, 1] .== 3 && Pop[end-1, :, 1] .== 4)
I get this error:
ERROR: TypeError: non-boolean (BitArray{1}) used in boolean context
Which sort of helps, can see that the two numeric arrays can not be compared in a boolean way. What is wrong with my syntax to get the count of the number of times both of the conditions are met. Simple I know but I can't get it! Thx. J

&& is a short-circuiting boolean, which means that if the first term is true, the rest isn't evaluated (see documentation). It also means it's only for a singular booleans and it cannot be broadcasted over an array.
& is the bitwise AND operator (documentation), that you want to use here, because it can be broadcasted over arrays with the syntax .&, the same way you use .==
julia> [true, true, false, false] .& [true, false, true, false]
4-element BitVector:
1
0
0
0
Update
in Julia 1.7+, the short-circuiting operators && and || can now be dotted to participate in broadcast fusion as .&& and .|| (#39594):
julia> [true, true, false, false] .&& [true, false, true, false]
4-element BitVector:
1
0
0
0

Related

Comparing two array values and deleting row if condition is fullfilled

I have an array with 2 columns. I want to compare the values of the first column, like this:
a[i+1]-a[i]<0.0025.
If this is true I need to delete the row with a[i+1].
This is my first attempt, but it doesnt work.
a = np.delete(a, np.diff(a[:,0])<0.0025, 0)
I get the following error:
ValueError: boolean array argument obj to delete must be one dimensional and match the axis length of 8628
8628 is the length of the array.
Another code i´ve tried is:
a = a[~(np.diff(a[:,0]))<0.0025]
But then I get this error:
TypeError: ufunc 'invert' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
Can somebody help me with this?
You're on the right track. np.diff(a[:, 0]) < 0.0025 creates an array of length 1 less than 8628, which means when you use it in np.delete that the dimension no longer matches with the original array.
I would go with your second attempt. Using < 0.0025 results in a mask of items that you want to delete, which you need to invert using ~ to get a mask of results you would like to keep. You have to make sure to place your parentheses correctly: ~( np.diff(a[:, 0]) < 0.0025 ). Instead, you can also use >= 0.0025 to make a mask of items you would like to keep.
Lastly, you have to make sure to match the dimensions (given that np.diff results in one less element. You can do this by prepending True to signify that you always want to keep the first value. One way to do that is using np.r_.
Final code:
import numpy as np
a = np.random.rand(8628, 2) # Your array here
result = a[ np.r_[True, np.diff(a[:, 0]) >= 0.0025] ]
Detailed example:
Consider the array: [ 1, 3, 2, 5, 3]
np.diff creates: [ 2, -1, 3, -2]
Using threshold creates: [True, False, True, False]
Note that when the next element in the original array is less than the previous,
the thresholding result in False too.
Finally, because there are now 4 values instead of 5, we prepend True.
This has the effect of always including the first element in the result:
Original: [ 1, 3, 2, 5, 3]
Mask [True, True, False, True, False]
^^^^ ~~~~ ~~~~~ ~~~~ ~~~~~
Then using boolean indexing, we get the elements where
the mask contains True to obtain the final result:
[1, 3, 5]

updating a document using the $max operator on arrays

i have the following document:
{
_id: 12,
item: 'envelope',
qty: ISODate("2021-12-05T00:00:00.000Z"),
arrayField: [ 128, 190, 1 ]
}
and i try to update it using this command
products> db.products.update({_id:12},{$max : { arrayField : [1,190,1879]} })
the output is as follows:
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 0,
upsertedCount: 0
}
I don't really understand how the comparison between the existing arrayField and the new one is being done. They are both Arrays, so there should be some kind of comparison on every element, but how exactly does it work?
From the documentation i read this:
With arrays, a less-than comparison or an ascending sort compares the smallest element of arrays, and a greater-than comparison or a descending sort compares the largest element of the arrays. As such, when comparing a field whose value is a single-element array (e.g. 1 ) with non-array fields (e.g. 2), the comparison is between 1 and 2. A comparison of an empty array (e.g. [ ]) treats the empty array as less than null or a missing field.
But i still don't understand exactly... Could someone provide an example in my case?
Thanks in advance
MongoDB takes the min or max, to represent the array in comparisons, for the query operators.
Numbers
{"ar" : [1,2,3]}
(<= ar 1) => (<= min(1,2,3) 3) => (<= 1 3) true
(>= ar 3) => (>= max(1,2,3) 3) => (<= 3 3) true
(= ar 2) => true because it contains the element
For empty arrays either < or > its always false compared to a number
Arrays
(again take the min if < , or max it >)
{"ar" : [1,2,3]}
(<= ar [0 1 2 3]) false because its like min(ar)=1 <min(0,1,2,3)=0
(= ar [1]) false we need all elements =
For the update $max operator
if both are arrays => elements are compared one by one.
max [1 2 3] [5] => [5]
max [1 2] [1 2 -100] => [1 2 -100]
Those are only for the $gte,$gt,$lt,$lte, $eq query operators.
The aggregate ones with same names are strict and don't work like this.
*Its not like complete because we have many types,i think the above are ok, answer might help, it was big to fit in comments.

Final logical value of boolean array in ruby

Lets say I have an array that looks like:
[true, true, false]
And I am passing an operator along with the array which may be AND, OR or XOR.
So I want to calculate the logical value of array based on the operator specified.
ex:
for the given array [true, true, false] and the operator AND
I should be able to perform in continuation for n number of elements in array
Steps: true AND true -> true, true AND false -> false
therefore the output should be false
the array can be an n number of boolean values.
The best and easiest way to do this is using reduce:
def logical_calculation(arr, op)
op=='AND' ? arr.reduce(:&) : op=='OR' ? arr.reduce(:|) : arr.reduce(:^)
end
and also the other way is might be using inject
OPS = { "AND" => :&, "OR" => :|, "XOR" => :^ }
def logical_calculation(array, op)
array.inject(&OPS[op])
end

How to iterate the ruby array without negative indices

I need to compare each value in ruby array with previous and next value.
Update
Example:
[1,2,4,5]
I want to check like this. (a[i] with a[i-1] and a[i+1])
1 with only next value # as there is no prev value
2 with prev & next value
4 with prev & next value
5 with only prev value # as there is no next value
In ruby, the a[-1] is not pointing to nil, it is taking last value. So, unable to iterate. Is there any alternate solution?
Tried
changing array to [nil,1,2,4,5,nil]
but getting following error
comparison of Fixnum with nil failed (ArgumentError)
instead of 0..n I tried 1...n. but this does not solve my issue.
Question:
How to ignore negative indices for first(i-1) and last(i+1) element in ruby array.
Your comparison doesn't really make sense. You are comparing everything twice, but if someone really is changing the array while you are iterating over it, you have much bigger problems than this (and you still will not catch modifications made to the beginning of the array when you are already in the middle). It is enough to compare each consecutive pair of elements, which is easily done:
[1, 2, 4, 5].each_cons(2).all? {|a, b| a < b }
If you really absolutely MUST compare triples, that is also easily done:
[1, 2, 4, 5].each_cons(3).all? {|a, b, c| a < b && b < c }
And if you want to make the size of the sliding window generic, then you can do something like this:
[1, 2, 4, 5].each_cons(n).all? {|window|
window.each_cons(2).map {|a, b| a < b }.inject(:&)
}
I need to compare each value in ruby array with previous and next
value.
This method takes an array and a comparison method such as :<, :> or :== etc
def prev_next arr, com
arr.map.with_index { |e,i|
if i == 0
[ e,
e.send(com,arr[i.succ])
]
elsif i == arr.length-1
[ e.send(com,arr[i.pred]),
e
]
else
[ e.send(com,arr[i.pred]),
e,
e.send(com,arr[i.succ])
]
end
}
end
arr = [1,2,3,4,5]
p prev_next(arr,:<)
#=> [[1, true], [false, 2, true], [false, 3, true], [false, 4, true], [false, 5]]
Note the second parameter can be passed as a string or a symbol because send is clever enough to convert strings to symbols.
Notable methods: Object#send, Fixnum#succ and Integer#pred
Now I totally agree with Jörg here that each_cons is the way to go and you should probably look for some other structure of the data if comparing the data is this complicated.
With that said. Nothing prevents normal index lookups in Ruby, and if nothing else works just implement your requirements in a simple case statement:
my_array = [1,2,4,5]
my_array.size.times do |ix|
case ix
when 0 then my_array[ix] == my_array[ix+1]
when my_array.size-1 then my_array[ix] == my_array[ix-1]
else my_array[ix-1] == my_array[ix] == my_array[ix+1]
end
end

Python - test all values in array against scalar value

I am trying to compare values in a numpy array with a scalar value.
Here is an example of this array. If it's any help it can only contain positive values.
y = np.array([ 1 , 0.008 , 3 , 4 , 5])
In another section of my code I want to compare this array with a scalar, say 3.5 in an 'if' statement used to break while loop.
I want to test if ANY of the values in the array is larger then this scalar value.
while True:
if any_value_in_array(y) > 3.5
break
#random code
Any command that would enable me of doing something like that?
You could use any() on the condition check
In [377]: (y > 3.5).any()
Out[377]: True
Longer Example
In [378]: y
Out[378]: array([ 1. , 0.008, 3. , 4. , 5. ])
In [379]: (y > 3.5)
Out[379]: array([False, False, False, True, True], dtype=bool)
In [380]: (y > 3.5).any()
Out[380]: True
Additionally, if you want to check if all elements match the condition, you could use all()

Resources