I'm encountering this problem and would like to seek your help.
The context:
I'm having a bag of balls, each of which has an age (red and blue) and color attributes.
What I want is to get the top 10 "youngest" balls and there are at most 3 blue balls (this means if there are more than 3 blue balls in the list of 10 youngest balls, then replace the "redudant" oldest blue balls with the youngest red balls)
To get top 10:
sel_balls = Ball.objects.all().sort('age')[:10]
Now, to also satisfy the conditions "at most 3 blue balls", I need to process further:
Iterate through sel_balls and count the number of blue balls (= B)
If B <= 3: do nothing
Else: get additional B - 3 red balls to replace the oldest (B - 3) blue balls (and these red balls must not have appeared in the original 10 balls already taken out). I figure I can do this by getting the oldest age value among the list of red balls and do another query like:
add_reds = Ball.objects.filter(age >= oldest_sel_age)[: B - 3]
My question is:
Is there any way that I can satisfy the constraints in only one query?
If I have to do 2 queries, is there any faster ways than the one method I mentioned above?
Thanks all.
Use Q for complex queries to the database: https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects
You should use annotate to do it.
See documentation.
.filter() before .annotate() gives 'WHERE'
.filter() after .annotate() gives 'HAVING' (this is what you need)
Related
In a Google Sheet with a cell range of 26x26 (so A1:Z26), I need to conditionally format (change the color to green) a rectangle area that is defined by user input.
Example of user input (4 values required):
hsize = 5 / vsize = 4 / starth = 3 / startv = 2
This means that the conditionally formatted area should be a rectangle from C2:G5 because the start cell horizontally is 3 (column C) and vertically 2 (row 2), and the size of the rectangle horizontally is 5 (C,D,E,F,G) and vertically 4 (2,3,4,5).
I already solved this with Apps Script but due to given restrictions I have to implement this without using any scripts.
I have numbered the whole 26x26 area (=sequence(26,26)) to get numbers from 1 to 676 that I could then use for the conditional formatting.
By doing this, I can limit the conditional formatting to the values between the start and the end value (in the example above that would be 29 (C2) and 111 (G5)). This works by using a simple and/if formula in the conditional formatting.
But the problem with this is that all the cells with values from 29 to 111 are now colored, not only the rectangle C2:G5.
I can't figure out how to define a formula that does what I need. How can I do this and limit the highlighted area to the defined cell range of the rectangle?
[Picture here]: green is the conditional formatting from 29 (C2) to 111 (G5), but what I actually need is that only the red-framed area should be shown in green.
try:
=REGEXMATCH(""&A1, "^"&TEXTJOIN("$|^", 1, INDIRECT(
ADDRESS($AB$4, $AB$3)&":"&ADDRESS($AB$2+$AB$4-1, $AB$1+$AB$3-1)))&"$")
or better:
=(COLUMN(A1)>=$AB$3) *(ROW(A1)>=$AB$4)*
(COLUMN(A1)<$AB$1+$AB$3)*(ROW(A1)<$AB$2+$AB$4)
I'm currently having trouble with conditional formatting for 3+ conditions.
What I want to do is that if 3 or more criteria are matched (or not matched, for a cell to turn a certain color.
Example:
There are multiple teams, their project priority, and the revenue they've made. I want to turn column C cells green or red based on A) the priority is "Medium" B) the team is "Korea Design" C) Green if $10K or above revenue, red if below $10K revenue. So if it matches A,B,C criteria, then the revenue column(C) will turn Green; alternatively if it matches A,B but not C (the revenue goal), then it will turn red.
*So first filtering that it is A and B, and then determining green or red depending on the revenue.
Thank you!
Sample Sheet
green:
=(A2="Korea Design")*(B2="Medium")*(C2>=10000)
red:
=(A2="Korea Design")*(B2="Medium")*(C2<10000)
I have a Google Sheet which is being populated by a Google Form. I am using Google Apps Script to add some extra functionality. Please feel free to access and modify these as needed in order to help.
Based on answers from the Form, I need to return a new date that factors in the time stamp at form submission.
This is a dumbed down example of what I need to do, but let's think of it like ordering a new car and its color determines how long it is going to take.
Car
Color
Toyota
Red
Honda
Blue
Tesla
Green
I need to write a conditional IF statement that determines how many weeks it will take to get the car based on the ordered color.
-
Red
Blue
Green
Toyota
1
3
5
Honda
2
4
6
Tesla
1
1
1
So if you order a Toyota in Red, it will take one week. If you order a Toyota in Green, it will take 5 weeks. If you order a Tesla, it will be really in one week no matter what color. Etc...
I started by writing some language in Sheets to take the Timestamp which is in Column A and add the appropriate amount of time to that:
=IFS(AND(B2 = "Toyota",C2 = "Red"),A2 + 7,AND(B2="Toyota",C2="Blue"), A2 + 21,AND(B2="Toyota",C2="Green"), A2 + 35,AND(B2 = "Honda",C2 = "Red"),A2 + 14,AND(B2="Honda",C2="Blue"), A2 + 28,AND(B2="Honda",C2="Green"), A2 + 42,AND(B2 = "Tesla"),A2 + 7)
And then I dragged that down the length of the entire column so that it would fill in as submissions came in.
However when you fill in the Google Form, it will overwrite what's in that entire row, blowing out what I had in that column.
Now I realized that the code needs to be written in Google Apps Script and returned as a value.
What kinds of modifications need to be made to my IFS statement in order to make it compatible with Google Apps Script?
For easier approach, QUERY would actually solve your issue without doing script as Broly mentioned in the comment. An approach you can try is to create a new sheet. Then have that sheet contain this formula on A1
Formula (A1):
=query('Form Responses 1'!A:C)
This will copy A:C range from the form responses, and then, copy/paste your formula for column Date Needed on column D.
Output:
Note:
Since you only copied A:C, it won't affect column D formula.
Your A:C in new sheet will update automatically, then the formula you inserted on D will recalculate once they are populated.
Add IFNA on your formula for column D to not show #N/A if A:C is still blank.
Formula (D2):
=IFNA(IFS(AND(B2 = "Toyota",C2 = "Red"),A2 + 7,AND(B2="Toyota",C2="Blue"), A2 + 21,AND(B2="Toyota",C2="Green"), A2 + 35,AND(B2 = "Honda",C2 = "Red"),A2 + 14,AND(B2="Honda",C2="Blue"), A2 + 28,AND(B2="Honda",C2="Green"), A2 + 42,AND(B2 = "Tesla"),A2 + 7), "")
I have this Google sheet, using sparklines to graph a change over time. I want a horizontal line at 2 different points, which cannot be done with a sparkline. So as a workaround, I have 3 different sparklines covering the same data but with different mins and maxes so I can draw a border between them.
But there are 6 parts (encircled in red) where lines are showing on the sparkline where they should not be.
What am I doing wrong?
https://docs.google.com/spreadsheets/d/1paFqu2hWAlpnzc3Ba0uo2kBfy9Inf2X6iWjQTzr_6XE/edit?usp=sharing
those are SPARKLINE glitches caused by ymax when the dataset contains the same consecutive values in the array (rows 10 & 11, 12 & 13 and 23 & 24) which are out of bound limited by ymax parameter.
an easy fix would be to slightly alter/manipulate duplicates before they hit the SPARKLINE output:
E17 cell:
=ARRAYFORMULA(SPARKLINE({A$3:A,
IF(COUNTIF(B$3:B, B$3:B)>1, B$3:B+(ROW(B$3:B)*0.0000000001), B$3:B)},
{"Ymin", 280; "Ymax", 285}))
E19 cell:
=ARRAYFORMULA(SPARKLINE({A$3:A,
IF(COUNTIF(B$3:B, B$3:B)>1, B$3:B+(ROW(B$3:B)*0.0000000001), B$3:B)},
{"Ymin", 275; "Ymax", 280}))
I have the following word list:
list = ['clogged drain', 'right wing', 'horse', 'bird', 'collision light']
I have the following data frame (notice spacing can be weird):
ID TEXT
1 you have clogged drain
2 the dog has a right wing clogged drain
3 the bird flew into collision light
4 the horse is here to horse around
5 bird bird bird
I want to create a table that shows keywords and frequency counts of how often the keywords occurred in TEXT field. However, if a keyword appears more than once in the same row within the TEXT column, it is only counted once.
Desired output:
keywords count
clogged drain 2
right wing 1
horse 1
bird 2
collision light 1
I have searched all over stackoverflow but couldn't find my specific case.
I would start by reformatting the TEXT column to get rid of your funny spacing, using str.split() and str.join(). Then, use str.contains for each of your keywords, and get the sum of the boolean values that are outputted (It will return True if your keyword is found):
# Reformat text, splitting wherever you have one or more spaces
df['formatted_text'] = df.TEXT.str.split('\s+').str.join(' ')
# create your output dataframe
df2 = pd.DataFrame(my_list, columns=['keywords'])
# Count occurences:
df2['count'] = df2['keywords'].apply(lambda x: df.formatted_text.str.contains(x).sum())
The result:
>>> df2
keywords count
0 clogged drain 2
1 right wing 1
2 horse 1
3 bird 2
4 collision light 1
Just to note, I changed the variable name of your list to my_list, so as not to mask the built in python data type
You can using extractall
df.TEXT.str.extractall(r'({})'.format('|'.join(list)))[0].str.get_dummies().sum(level=0).gt(0).astype(int).sum()
Out[225]:
bird 2
clogged drain 2
collision light 1
horse 1
right wing 1
dtype: int64