Spotfire - Identify each time a value changes in a particular pattern for a particular type - spotfire

Apologies for the bad title, I'm struggling to describe exactly what I;m trying to do (which has also made it difficult to search for an existing answer.
I have a series of date with the columns "Asset", "Time", and a "State" that is a calculated column that changes based on several other values. The data is source from a constant, and non-regular stream of data (though in the table below I have created a sample of timestamps that are regular).
The below table shows the source data ("Asset", "Time" and "State"), as well as an intended calculated column "Event" that tracks each time an event starts. I do not simply want to count the number of times an "Asset" has a Bad "State", but identify each time an "Asset" changes from a "State" of Good to a state of Bad (note in the real data there is a large number of different states, but the pattern I'm trying to identify is consistent).
+-------+----------+-------+-------+
| Asset | Time | State | Event |
+-------+----------+-------+-------+
| 1 | 12:00:00 | Good | 0 |
| 2 | 12:00:00 | Good | 0 |
| 1 | 12:00:01 | Good | 0 |
| 2 | 12:00:01 | Good | 0 |
| 1 | 12:00:02 | Bad | 1 |
| 2 | 12:00:02 | Good | 0 |
| 2 | 12:00:03 | Good | 0 |
| 2 | 12:00:03 | Good | 0 |
| 1 | 12:00:04 | Bad | 0 |
| 1 | 12:00:04 | Good | 0 |
| 2 | 12:00:05 | Good | 0 |
| 2 | 12:00:05 | Bad | 1 |
| 2 | 12:00:06 | Bad | 0 |
| 1 | 12:00:06 | Good | 0 |
| 2 | 12:00:07 | Bad | 0 |
| 2 | 12:00:07 | Good | 0 |
| 2 | 12:00:08 | Good | 0 |
| 1 | 12:00:08 | Bad | 1 |
| 2 | 12:00:09 | Good | 0 |
| 1 | 12:00:09 | Bad | 0 |
| 2 | 12:00:10 | Good | 0 |
| 1 | 12:00:10 | Good | 0 |
+-------+----------+-------+-------+
I intend to create a chart for this data to show how many times an event occurs for a particular asset per day. I figured the easiest way to do that is to have a column that counts a 1 when the event starts, and then sum this column over the dates to create the visualisation.
My idea was for a calculated column that picks up when the "State" is bad, and then checks to see if the previous state for that "Asset" was good, and set as a 1 if so. I have so far been unable to find a way to identify what the value was for a previous row entry for a particular "Asset".
Note that there are roughly 100 (or more) individual "Asset" entries, so creating an individual calculated column to track each would not be feasible. I am also using Spotfire 7.1.
Thanks in advance, and sorry again if the way I've written this is confusing.

Related

Using Excel to GROUP BY and find date WHERE MAX

My problem is I have a table of data structured as below :
+---------------+------------+---------+
| recipe number | date | quality |
+---------------+------------+---------+
| 154 | 01/01/2020 | 2 |
| 154 | 01/03/2020 | 3 |
| 154 | 01/05/2020 | 1 |
| 154 | 01/07/2020 | 2 |
| 222 | 01/01/2020 | 3 |
| 222 | 01/03/2020 | 2 |
| 222 | 01/05/2020 | 2 |
| 222 | 01/07/2020 | 1 |
| 888 | 01/01/2020 | 1 |
| 888 | 01/03/2020 | 3 |
| 888 | 01/05/2020 | 2 |
| 888 | 01/07/2020 | 3 |
| 666 | 01/01/2020 | 2 |
| 666 | 01/03/2020 | 3 |
| 666 | 01/05/2020 | 3 |
| 666 | 01/07/2020 | 3 |
| 777 | 01/01/2020 | 1 |
| 777 | 01/03/2020 | 2 |
| 777 | 01/05/2020 | 3 |
| 777 | 01/07/2020 | 1 |
| 123 | 01/09/2020 | 3 |
| 254 | 01/01/2020 | 2 |
| 254 | 01/03/2020 | 3 |
| 745 | 01/01/2020 | 1 |
| 745 | 01/03/2020 | 3 |
| 745 | 01/05/2020 | 2 |
| 745 | 01/07/2020 | 3 |
| 578 | 01/11/2020 | 3 |
| 578 | 01/01/2021 | 3 |
| 578 | 01/03/2021 | 1 |
| 578 | 01/05/2021 | 3 |
| 678 | 01/07/2021 | 2 |
| 999 | 01/09/2021 | 1 |
| 999 | 01/11/2021 | 1 |
+---------------+------------+---------+
The final answer I want is that I need a table of each recipe number and a simple yes/no whether that recipe decreased in quality over time, at all.
There are some recipes which only have one entry, and others which only increased in quality - these need to be answered "no"
EG:
recipe
decreased?
154
yes
666
no
Unfortunately, I'm limited to only Excel for this, though I understand doing it in other environments is probably easier.
I have tried a max(index+match) to see if I can return the highest quality for each recipe (and the lowest with a min). But I got stuck at trying to get Excel to return an array of qualities conditional on which recipe to look at.
I also tried PowerQuery but the problem seems too complex for that utility.
I've done some more thinking and some psuedocode that would solve it is:
For each recipe number:
1) Find me the max quality and the date where it happened
2) Find me any quality lower than this number where the date it happened is
after step 1
3) If the date of step 1 is earlier (less than) the date of step 2, output
"yes", otherwise "no"
Translating that into Excel 2016 is a bit difficult
Edit: Thanks to #TomSharpe who pointed out some logic errors => incorrect results, I have had to modify the M-code and also remove the formula method. I believe the code below satisfies your requirements
This can be done in Power Query
Group by Recipe
Determine the first date of the highest quality
See if any dates after the first date have a lower quality
If so then "yes" else "no"
Examine the comments and step through the Applied Steps window to better understand the algorithm.
M Code
let
//read in the data
//change table name in next line to actual table name
Source = Excel.CurrentWorkbook(){[Name="Table18"]}[Content],
//set data types
#"Changed Type" = Table.TransformColumnTypes(Source,{{"recipe number", Int64.Type}, {"date", type date}, {"quality", Int64.Type}}),
//group by recipe number
#"Grouped Rows" = Table.Group(#"Changed Type", {"recipe number"}, {
//(t) is each subtable returned
{"Quality Decrease", (t)=>
let
//List.Max(quality) => highest quality rating
//Filter the subtable to only show qualities of that value
//then, with List.Min(....[date]) return the earliest date
firstBest= List.Min(Table.SelectRows(t, each [quality] = List.Max(t[quality]))[date]),
//Filter the subtable to only show dates > firstBest date and with quality worse than the highest quality rating
decrQual = Table.SelectRows(t, each [date] > firstBest and [quality] < List.Max(t[quality]))
in
//check if resultant table is empty
if Table.IsEmpty(decrQual) then "no" else "yes", Text.Type
}
})
in
#"Grouped Rows"

Grouping a list of items in to as equal in numbers as possible

Requirement: Split a list in to 4 separate groups, based on a value for each row.
| Player | Skill |
| ------------- |:-------------:|
| Player 1 | 10000 |
| Player 2 | 50000 |
| Player 3 | 2000 |
| Player 4 | 11000 |
| Player 5 | 7525 |
| Player 6 | 100 |
| Player 7 | 999 |
| Player 8 | 14579 |
| Player 9 | 26700 |
So in the example above, these players would be split in to 4 groups:
| Group | # of players |
| ------------- |:-------------:|
| Group1 | 2 |
| Group2 | 2 |
| Group3 | 2 |
| Group4 | 3 |
The number of players in a group needs to be as close as possible, however, as a group, the groups total Skill needs to around similar in numbers each time.
Before I go too far down the rabbit hole (as wording a question like this in a simple google search is not turning out very well) are there any built in functions of Excel that can be leveraged to achieve this or possible efforts in VBA that can be explored to achieve the required result?
This isn't an answer! But suppose you try a simple algorithm:
Calculate average skill level (ASL) for all 9 players
Set TSG (total skill for group) to zero.
Loop:Take largest skill Level (LSL) of remaining players
If TSG+LSL>ASL
Go to next group
Else
Add to total skill (TSG) for this group
Remove player from list
Repeat loop until no players remaining.
If you apply this by hand to your data you should get:
Average=30725.75
+---------+---------+---------+---------+
| Group 1 | Group 2 | Group 3 | Group 4 |
+---------+---------+---------+---------+
| 50000 | 26700 | 14579 | 10000 |
| | 2000 | 11000 | 7525 |
| | 999 | | |
| | 100 | | |
| | | | |
| 50000 | 29799 | 25579 | 17525 |
+---------+---------+---------+---------+
Clearly there are a couple of issues - you might not want a single group containing only player with highest skill level. Also you might want to re-average the remaining players after taking out the most skilful player. Should be a starting point though - could be implemented fairly easily with formulas or VBA.

values of new table changing dynamically with the input of the initial table

I have a question in Excel and need your help!
I can do this if it was static problem but I need my end result to adjust to my input in the table because the year sometimes the year finishes sooner or later or is different or the number of activities vary.
Initial table (It always go in chronological order and it only has 1 or nothing. (I put 0 there because I wanted to put space and didn't know how to do it. also Number of activities may vary)
+----------------+------+------+------+------+------+------+
| year | 2016 | 2016 | 2016 | 2017 | 2017 | 2017 |
+----------------+------+------+------+------+------+------+
| month calendar | 10 | 11 | 12 | 1 | 2 | 3 |
| month project | 1 | 2 | 3 | 4 | 5 | 6 |
| Activity 1 | 1 | 1 | 0 | 0 | 0 | 0 |
| Activity 2 | 0 | 0 | 1 | 1 | 1 | 1 |
| Activity 3 | 0 | 0 | 0 | 1 | 1 | 0 |
| Activity 4 | 0 | 1 | 1 | 0 | 0 | 0 |
| Activity 5 | 1 | 1 | 1 | 1 | 1 | 1 |
+----------------+------+------+------+------+------+------+
I want in another sheet
+---------------+------------+------------+------------+------------+
| Activity year | 2016 | | | |
| | | | | |
| Activity 1 | Activity 2 | Activity 3 | Activity 4 | Activity 5 |
| 25,0% | 12,5% | 0,0% | 25,0% | 37,5% |
| | | | | |
| Activity year | 2017 | | | |
| | | | | |
| Activity 1 | Activity 2 | Activity 3 | Activity 4 | Activity 5 |
| 0,0% | 37,5% | 25,0% | 0,0% | 37,5% |
+---------------+------------+------------+------------+------------+
Now imagine that in the "another sheet" I have nothing and I want the result to adjust to the initial table. How can I do this?
Sorry for bad editing but I can't do better.
Any help is good thank you, I answer any question you might have.
I'm going to add something that is related to this and I also need. I need a formula to get the number of different activities per year that happen at least once for my calculations later. In this case it would be a formula for 2016 which the result is 4 and 2017 is 3.

How to account for quantity of items in a ratio formula in Excel?

I am trying to find a ratio-like formula that takes into account the difference between the number of items in stock and those that are on sale, as well as the actual number of items in stock and on sale.
The difference between 2 and 1 is not important and throws off the reports.
The difference between 20,000 and 10,000 is way more important.
However, The different between 2000 and 10 though is even more important.
Just a simple ratio would usually work but not in this case since the actual quantity of items (or those on sale) are not accounted for...I get a .4 ratio when only 5 items are in stock (Item 9 below).
I looked at using the percentage difference first but it wouldn't work even if the amount of items in stock are taken into account being that numbers can be identical (items 12 & 13 below).
Let me know if I need to clarify.
+-----------+-----------+---------+--------+-----------+
| Item Name | In stock | On Sale | Ratio | Perc Diff |
+-----------+-----------+---------+--------+-----------+
| Item 12 | 1 | 1 | 1.0000 | 0.0000 |
| Item 13 | 1 | 1 | 1.0000 | 0.0000 |
| Item 1 | 1,000 | 500 | 0.5000 | -0.5000 |
| Item 2 | 900 | 400 | 0.4444 | -0.5556 |
| Item 9 | 5 | 2 | 0.4000 | -0.6000 |
| Item 3 | 800 | 300 | 0.3750 | -0.6250 |
| Item 8 | 300 | 100 | 0.3333 | -0.6667 |
| Item 11 | 3 | 1 | 0.3333 | -0.6667 |
| Item 4 | 700 | 200 | 0.2857 | -0.7143 |
| Item 7 | 400 | 100 | 0.2500 | -0.7500 |
| Item 10 | 4 | 1 | 0.2500 | -0.7500 |
| Item 6 | 500 | 100 | 0.2000 | -0.8000 |
| Item 5 | 600 | 100 | 0.1667 | -0.8333 |
+-----------+-----------+---------+--------+-----------+
Providing a weight of the percentage difference against the absolute or instock value should improve your results, I needed to add an image to explain what I was doing properly.

Transform values without VBA but with Index and Match

I'm trying to find a solution without macros in excel for following problem:
There is a table containing ratings of a student for different time periods.
So the rating of the student with ID=1 was 1 from January to April and 3 from Mai to June.
Two other students had a constant ranking (6 and 9) from January to June
| A | B | C |D |
---| ----|------------|------------|-------|
1 | ID | START | END |RANKING|
2 | 1 | 01.01.2014 | 30.04.2014 | 1 |
3 | 1 | 01.05.2014 | 30.06.2014 | 3 |
4 | 2 | 01.01.2014 | 30.06.2014 | 6 |
5 | 3 | 01.01.2014 | 30.06.2014 | 9 |
Next table contains IDs (y axis) and Months (x axis)
| F | G | H | I | J | K | L |
---| ----|--------|--------|--------|--------|--------|--------|
1 | ID | 201401 | 201402 | 201403 | 201404 | 201405 | 201406 |
2 | 1 | | | | | | |
3 | 2 | | | | | | |
4 | 3 | | | | | | |
And I wish to feel this second table like this:
| ID | 201401 | 201402 | 201403 | 201404 | 201405 | 201406 |
| ----|--------|--------|--------|--------|--------|--------|
| 1 | 1 | 1 | 1 | 1 | 3 | 3 |
| 2 | 6 | 6 | 6 | 6 | 6 | 6 |
| 3 | 9 | 9 | 9 | 9 | 9 | 9 |
I tried to use Index and Match, but without any good results because I haven't found a posibility to use IF (if (
Could anybody help?
You can get what you're looking for with SUMPRODUCT
Given the layout you provided, this formula should work when put in G2 and filled down and over
=SUMPRODUCT(--($A:$A=$F2),--($B:$B<=G$1),--($C:$C>G$1),$D:$D)
That looks in column A for an ID matching F2, then for every one it finds of those:
It checks the date in column B against the date in G1
It checks the date in column C against the date in G1
If all criteria match, it returns the value in Column D
This assumes you only have one entry for each period, otherwise it will sum them.
Also, you can use SUMIFS, it's a little less easy to read but I think it's slightly more efficient than SUMPRODUCT (I'm not positive, just anecdotal evidence from usage)
=SUMIFS($D:$D,$A:$A,"="&$F3,$B:$B,"<="&G$1,$C:$C,">"&G$1)
It does the exact same thing, just with different syntax.

Resources