Django ORM: AND'ing and exclude query - django-queryset

I want to select items where more than one of the values are greater than 0.
class Item(models.Model):
val1 = models.PositiveIntegerField()
val2 = models.PositiveIntegerField()
val3 = models.PositiveIntegerField()
I thought these should do by eliminating items where all vals are 0:
Item.objects.exclude(val1=0, val2=0, val3=0)
Item.objects.exclude(Q(val1=0) & Q(val2=0) & Q(val3=0))
They both eliminate every item where a val is zero and return only the ones with all vals greater than 0. I don't want to OR the combinations but find a generic expression because vals can be more than 3.
How can the query be written? Thanks.

You could use chained filters to do this:
Item.objects.filter(val1__gt=0).filter(val2__gt=0).filter(val3__gt=0)
Using the filter __gt selects only values that are greater than the value. Chaining filters acts as logical AND statements so this would exclude any that are 0 for all three values.
Edit:
As per your comment clarifying your actual needs, something like this may work. (It is untested)
Item.objects.filter((Q(val1__gt=0) & Q(val2__gt=0)) |
(Q(val2__gt=0) & Q(val3__gt=0)) |
(Q(val1__gt=0) & Q(val3__gt=0)))
Binding multiple AND and OR operators in the right order should get you what you need.

Related

FILTER values from one sheet when not present on another

I'm trying to compare Items in "projectEstimate!D2:D & projectEstimate!E2:E" to Items in 'itemsAssociations!C3:C & itemsAssociations!D3:D" for matches.
If there is a match, confirm that the associated item (itemsAssociations!G3:G & itemsAssociations!H3:H) is not already listed in "projectEstimate".
If it is not listed, print that item. If it IS listed, do nothing.
I put together the following code which seems like it should work, but the item prints whether it's present on projectEstimate or not.
=ArrayFormula({itemsAssociations!I2:J2;FILTER(itemsAssociations!I3:J,
{projectEstimate!D2:D&IF(LEN(projectEstimate!E2:E),projectEstimate!E2:E,)=itemsAssociations!C3:C&IF(LEN(itemsAssociations!D3:D),itemsAssociations!D3:D,)},
{projectEstimate!D2:D&IF(LEN(projectEstimate!E2:E),projectEstimate!E2:E,)<>itemsAssociations!G3:G&IF(LEN(itemsAssociations!H3:H),itemsAssociations!H3:H,)}
)})
I also tried this QUERY, but not sure how to include the entire ranges
=QUERY(itemsAssociations!C3:J,"SELECT I,J WHERE C = '"&projectEstimate!D2:D&"' AND D = '"&projectEstimate!E2:E&"' AND J != '"&projectEstimate!D2:D&"'",0)
This is close, but the opposite result:
=FILTER(projectEstimate!D2:D,COUNTIF(FILTER(itemsAssociations!J3:J,COUNTIF(itemsAssociations!C3:C&itemsAssociations!D3:D,itemsAssociations!C3:C&itemsAssociations!D3:D)),projectEstimate!D2:D))
My sheet
it would be something amongst theses lines:
=ARRAYFORMULA(REGEXREPLACE(QUERY(FILTER(projectEstimate!D2:D&":"&projectEstimate!E2:E,
NOT(COUNTIF(itemsAssociations!C3:C&":"&itemsAssociations!D2:D,projectEstimate!D2:D&":"&projectEstimate!E2:E))),
"where Col1 is not null", 0), ":$", ))
This is what I came up with...
=IFERROR(FILTER(FILTER(itemsAssociations!J3:J,NOT(COUNTIF(projectEstimate!D3:D,itemsAssociations!C3:C))),NOT(COUNTIF(FILTER(projectEstimate!D2:E,NOT(COUNTIF(itemsAssociations!C3:C&itemsAssociations!D3:D,projectEstimate!D2:D&projectEstimate!E2:E))),FILTER(itemsAssociations!J3:J,NOT(COUNTIF(projectEstimate!D3:D,itemsAssociations!C3:C)))))),"No suggested items!")

Get Capped Maximum Value From List

I have a list of values that range anywhere from 500-1000. I have a second list of values that denote relevant breakpoints in the 500-1000 range (500, 520, 540, 600, etc). I need to return the highest value in the second list that is less than the value in a given number from the first list. I noticed the "N" functions let you set a conditional on them, so for example if I do:
List.Max(List.FirstN(SomeTable[Breakpoints], each _ < 530))
It correctly returns 520 to me. However if I put this inside an AddColumn function and change the 530 to a local field reference:
Table.AddColumn(MyTable, "MinValue", each List.Max(List.FirstN(SomeTable[Breakpoints], each _ < [SomeNumbers])))
Then I get a "We cannot apply field access to the type Number" error. Is what I'm trying to do possible and I'm just formatting it wrong? I always get confused with scope and references in PQ, so it may just be that.
After each, [SomeNumbers] by itself is short for _[SomeNumbers] (which is what you see when filtering a column). In the List.FirstN call, _ refers to a number in the list instead of a row in a table: the value of _ is tied to the closest each, where closeness is measured by the number of layers of nesting between _ and the appearance of each . Therefore, in your code [SomeNumbers] is trying to find the column SomeNumbers on a number, which doesn't exist.
There are a couple ways to fix this:
You can use a let...in statement to store the current value of the SomeNumbers column to use it for later, like so:
each
let
currentNumber = [SomeNumbers],
result = List.Max(List.FirstN(SomeTable[Breakpoints], each _ < currentNumber))
in
result
You can explicitly define a function with the (x) => ... syntax instead of using each twice, like so:
each List.Max(List.FirstN(SomeTable[Breakpoints], (point) => point < [SomeNumbers]))

How to filter one list of items from another list of items?

I have a huge list of items in Column A (1,000 items) and a smaller list of items in Column B (510 items).
I want to put a formula in Column C to show only the Column A items not in Column B.
How to achieve this through a formula, preferably a FILTER formula?
Select the list in column A
Right-Click and select Name a Range...
Enter "ColumnToSearch"
Click cell C1
Enter this formula: =MATCH(B1,ColumnToSearch,0)
Drag the formula down for all items in B
If the formula fails to find a match, it will be marked "#N/A", otherwise it will be a number.
If you'd like it to be TRUE for match and FALSE for no match, use this formula instead:
=ISNUMBER(MATCH(B1,ColumnToSearch,0))
If you'd like to return the unfound value and return empty string for found values
=IF(ISNUMBER(MATCH(B1,ColumnToSearch,0)),"",B1)
Alternative method is simply =
FILTER(A1:A,if(COUNTIF(B1:B,A1:A),0,1))
It's much more efficient.
It uses countif to get a 0 or a 1 as an array if the values in B are in A, then it reverses the 0 and 1 to get the values that are missing instead of only the values that are in there. It then filters based on that.
Columns look like this
A B
1 2
2 5
3
4
5
ARE formulae:
=FILTER(A1:A, MATCH(A1:A, B1:B, 0))
=FILTER(A1:A, COUNTIF(B1:B, A1:A))
ARE NOT formulae:
=FILTER(A1:A, ISNA(MATCH(A1:A, B1:B, 0)))
=FILTER(A1:A, NOT(COUNTIF(B1:B, A1:A)))
in your case:
=FILTER(A1:A; ISNA(MATCH(A:A; B:B; )))
if you face a mismatch of ranges see: https://stackoverflow.com/a/54795616/5632629

USing AddExpression / MathExpression in Weka

I am working on a very basic WEKA assignment, and I'm trying to use WEKA to preprocess data from the GUI (most current version). I am trying to do very basic if statements and mathematical statements in the expression box when double clicking on MathExpression and I haven't had any success. For example I want to do
if (a5 == 2 || a5 == 0) then y = 1; else y = 0
Many different variations of this haven't worked for me and I'm also unclear on how to refer to "y" or if it needs a reference within the line.
Another example is -abs(log(a7)–3) which I wasn't able to work out either. Any ideas about how to make these statements work?
From javadoc of MathExpression
The 'A'
letter refers to the value of the attribute being processed.
Other attribute values (numeric only) can be accessed through
the variables A1, A2, A3, ...
Your filter applies to all attributes of your dataset. If I load iris dataset and apply following filter.
weka.filters.unsupervised.attribute.MathExpression -E log(A).
your attribute ,sepallength values change as following.
Before Filter After Filter
Minimum 4.3 Minimum 1.459
Maximum 7.9 Maximum 2.067
Mean 5.843 Mean 1.755
StdDev 0.828 StdDev 0.141
Also if you look to javadoc, there is no if else function but ifelse function. Therefore you should write something like
ifelse ( (A == 2 || A == 0), 1,0 )
Also this filter applies to all attributes. If you want to change only one attribute and according to other attribute values ; then you need to use "Ignore range option" and use A1,A2 to refer to other attribute values.
if you need to add new attribute use AddExpression.
An instance filter that creates a new attribute by applying a mathematical expression to existing attributes.

Is it better to use NOT or <> when comparing values?

Is it better to use NOT or to use <> when comparing values in VBScript?
is this:
If NOT value1 = value2 Then
or this:
If value1 <> value2 Then
better?
EDIT:
Here is my counterargument.
When looking to logically negate a Boolean value you would use the NOT operator, so this is correct:
If NOT boolValue1 Then
and when a comparison is made in the case of the first example a Boolean value is returned. either the values are equal True, or they are not False. So using the NOT operator would be appropriate, because you are logically negating a Boolean value.
For readability placing the comparison in parenthesis would probably help.
The latter (<>), because the meaning of the former isn't clear unless you have a perfect understanding of the order of operations as it applies to the Not and = operators: a subtlety which is easy to miss.
Because "not ... =" is two operations and "<>" is only one, it is faster to use "<>".Here is a quick experiment to prove it:
StartTime = Timer
For x = 1 to 100000000
If 4 <> 3 Then
End if
Next
WScript.echo Timer-StartTime
StartTime = Timer
For x = 1 to 100000000
If Not (4 = 3) Then
End if
Next
WScript.echo Timer-StartTime
The results I get on my machine:
4.783203
5.552734
Agreed, code readability is very important for others, but more importantly yourself. Imagine how difficult it would be to understand the first example in comparison to the second.
If code takes more than a few seconds to read (understand), perhaps there is a better way to write it. In this case, the second way.
The second example would be the one to go with, not just for readability, but because of the fact that in the first example, If NOT value1 would return a boolean value to be compared against value2. IOW, you need to rewrite that example as
If NOT (value1 = value2)
which just makes the use of the NOT keyword pointless.

Resources