If I want to compute latest X (e.g. 100) value's average, and this average is within (y, z) value, I think I can only create customized method? customized accumulate function will not work since accumulate function(getResult(Serializable context)) can only accept one parameter.
I'm not sure where you got the impression that accumulate only takes a single parameter. You should refer to the official Drools documentation, not random posts on the internet since they're generally wrong.
This is how the documentation describes the accumulate function:
accumulate
Use this to iterate over a collection of objects, execute custom actions for each of the elements, and return one or more result objects (if the constraints evaluate to true). This element is a more flexible and powerful form of the collect condition element. You can use predefined functions in your accumulate conditions or implement custom functions as needed. You can also use the abbreviation acc for accumulate in rule conditions.
Use the following format to define accumulate conditions in rules:
accumulate( <source pattern>; <functions> [;<constraints>] )
Using this, and the built-in average function, we can come up with something like this:
rule "Example"
when
accumulate( SensorReading( $temperature: temperature );
$avg : average( $temperature );
$avg > 30, $avg < 35 )
then
// only triggers when temperature average is between 30 and 35
end
Here, we're going to accumulate over SensorReading objects, taking the average temperature, and only triggering the right hand side when the average is between 30 and 35.
Related
Write a recursive function to find the smallest element in a vector.
We can not use loops but can use if statements.
Using RECURSION is a must.
I Could Not think of any solution, the main problem was if I define a function then I have to give it some value and if I do so then whenever recursion occur it will again reset the value of that variable.
function miminimumis=minimumval(k)
aa=k(1);
k=k(k<k(1));
if length(k)==0
miminimumis=aa;
else
% this line gives the recursion
miminimumis=minimumval(k);
end
end
here we create a new array which consists of elements only smaller than the first element. if this array is empty then it means that first element is min, if not we do the same for the new array unless we reach an empty array. the recursion is provided by using the same function in the definition of the function.
Solutions which in the worst case reduce the problem size by 1 will cause the recursive stack to have O(length(array)) growth. An example of this would be when you filter the array to yield values less than the first element when the array is in descending order. This will inevitably lead to stack overflow for sufficiently large arrays. To avoid this, you want to use a recursion which splits the problem of size n into two subproblems of size n/2, yielding O(log(length(array))).
I'm not a Matlab user/programmer, so I'll express the algorithm in pseudo-code. The following assumes that arrays are 1-based and that there is a built-in function min(a,b) which yields the minimum of two scalars, a and b. (If not, it's easy to replace min() with if/else logic.)
function min_element(ary) {
if length(ary) == 1 {
return ary[1]
}
split ary into first_half, second_half which differ in length by no more than 1
return min( min_element(first_half), min_element(second_half) )
}
This could alternatively be written using two additional arguments for the lo_index and hi_index to search between. Calculate the midpoint as the integer average of the low and high indices, and make the two recursive calls min_element(ary, lo_index, mid) and min_element(ary, mid+1, hi_index). The base condition is when lo_index == hi_index, in which case you return that element. This should be faster, since it uses simple integer arithmetic and avoids creating sub-arrays for the subproblems. It has the trade-off of being slightly less friendly to the end user, who has to start the process by calling min_element(ary, 1, length(ary)).
If the stack limit is 500, you'll be limited to arrays of length < 500 using linear stack growth algorithms. With the divide-and-conquer algorithm described above, you won't get stack overflow unless you have an array of length ~2500, much bigger than any array you could actually create.
I am working in Tableau and trying to create a formula that will return me the value of each customer that walks into a store by dividing Net Sales / Traffic. When I try to combine the two separate formulas, it gives me the following error: Cannot mix aggregate and non-aggregate arguments with this function. The two functions I created that I'm trying to divide are:
SOT = (SUM([Sales Net])-SUM([Sales Gcard Net]))/SUM([Traffic Perday]) and SOT Goal
When I look at it in Tableau, it's stating that SOT is an aggregate function. How do I work around this to be able to get
SOT / SOT Goal
Aggregate variables are values that are calculated in the view, and depend on the level of aggregation in Tableau. e.g. sum(Sales) will show different values in Tableau if it’s next to a Region dimension, or if it’s next to a Category dimension.
In order to avoid the errors you can use many solutions. My favorite is indeed LOD expressions. In your view, though I do not have required sample data and therefore, I cannot try my hands on different possibilities here, I suggest that this should work-
SOT = ({SUM([Sales Net])}-{SUM([Sales Gcard Net])})/{SUM([Traffic Perday])}
Do remember that this solution will over-ride your filters and if you are using filters you have to add all those to Context.
EDIT
While trying different possibilities remember these things...
{SUM([Sales])} will sum the sales over entire data and {} i.e. curly braces wrapped around the sum function will cause to return the value as non-aggregate. In other words, this will work as LOD and if you'll add this field to view, the sum of entire sales will be shown against each row.
{FIXED [DIMENSION NAME] : sum([Sales])} will sum sales separately for each Dimension value. Fixed statement (LOD) again returns the value as non-aggregate value. if you'll add this field to view, the sum of entire sales for that dimension will be shown against each dimension.
I am using Apple's Accelerate Framework, vDSP biquad function https://developer.apple.com/documentation/accelerate/1450838-vdsp_biquad?language=objc#parameters in order to emulate pythons sosfilt function. I have done all the filtering but notice I have transient signals that I am trying to remove. In python, this is done with finding the initial conditions from sosfilt_zi https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.sosfilt_zi.html#scipy.signal.sosfilt_zi and multiplying by the first element in the data that is being filtered. I followed this amazing example Matlab filtfilt() function implementation in Java.
When I print out the initial conditions in python using sosfilt_zi, I am getting two values for each section (I'm using a second-order cascade) so I have four values in total.
However in the single channel biquad function for iOS, they are asking for (2*M)+2 for the Delay. I was assuming that the initial conditions are related to the Delay and that this is what I would need to change in order to adjust my signal and remove the transient.
The function definition for the Delay Parameter for the biquad function in iOS is " An array of single-precision values initialized with direct-form 1 “past” state data for each section of the biquad. The length of the array should be (2 * M) + 2, where M is the number of sections. For each section m, Delay[2m:2m+1] represent the two delayed input values for section m and Delay[2M:2M+1] represent the two delayed output values of the filter. After this function executes, this array contains the final state data of the filters."
If I have 2 sections, then my delay array should look like :
[0:1] - input delay value for section 0
[2:3] - input delay value for section 1
[4:5] - output delay value
I initially had the Delay set to an array of 6 zeros. If the output of sosfilt_zi would be the proper values for the two input sections of the Delay, then how could I find the delayed output values of the filter?
Is anyone familiar with vDSP and able to remove transient signals or can explain how to adjust the Delay values for a cascaded second-order sections? Is adjusting the Delay values the correct move and how could I get these values in python?
I was thinking that my delay array would look like (using values shown in second link below):
[0.72095219 -0.28358224] - section 0
[-0.80004591 0.80004591] - section 1
However, I don't know what that output would be if this is even correct. I'd appreciate any help! I've found really little documentation or examples on the iOS biquad function. Thank you!
Butterworth Bandpass filter - Initial Conditions is being applied
Output of sosfilt_zi - gives inital conditions
Result of Biquad Filter from iOS vDSP on top and result of sosfilt with initial conditions on bottom
Delays being initialized
Biquad Function
What is the most effective procedure or equivalent for "head" & "tail" in Tableau if you are try to isolate the last or first items of an vector?
The known procedure e.g. in R is easy if you are looking for an average of the last 10 numbers:
mean(head(x, 10)) or mean(tail(x, 10)).
I try to find a solution in Tableau with LOD "max" & "min" but "show me the first 10 min items"?! No chance!
If you are talking about table calculations, then you can use the WINDOW_XXX() functions -- such as window_sum(sum(x), 1, 10) or window_avg(sum(x), size()-9, size())
Table calcs operate on the aggregated query results returned from the data source, hence the aggregation function sum() around the field x.
It might be simpler to learn to use Top N filters instead table calcs, depending on what problem you are trying to solve.
I've a problem to calculate weighted standard deviation. Here's the formula I used:
sum([Weight]*(([Variable]-[Mean Score - Variable])^2))
/
SUM([Weight])
But there's a error pop up message "Cannot mix aggregrate and non-aggregrate"
I wonder what's wrong with my formula?
Thanks
I am assuming Variable and Weight are explicit fields in your dataset, while [Mean Score] is a calculated field you defined in Tableau.
[Mean Score] is an aggregate calculation; Variable is not. You can check this by dragging [Mean Score] to any shelf in Tableau, and note that it is show within the prefix AGG(). Note that you can't select the form of aggregation (SUM, MIN, AVG) to apply in that case, because the aggregation function is defined within that calculation.
You can't mix aggregate and record level calculations directly. Record level calculations are evaluated once for each individual data row. Aggregate calculations are evaluated once for each block of data rows.
The dimensions used in your worksheet determine which data rows are grouped together into blocks (partitioning the data). Analogous to the fields that follow the keyword GROUP BY in SQL select statement. As with SQL, the other fields referenced must be aggregated somehow such as via a SUM(), MIN(), MAX() or other call. Tableau calls those fields measures.
The most straightforward solution is to revise your definition of [Mean Score] to make it a Level Of Detail (LOD) calc instead of an aggregate calc.
That will allow you to essentially first compute the mean score separately, and then reference that result in your record level calculation. You will have to decide among 3 different ways for determining the dimensions for your LOD calc. See the online help for more info on LOD calcs.
For example, try replacing [Mean Score] with { include : [Mean Score] }