I am trying to find the closest value in this Poisson Distribution table to help create some variation in my NHL game simulator. Right now I have the minimum value set to =(MAX(H4:R14)/1.25) and the max as MAX(H4:R14). My rand (random) value is set to =RAND()*($V$4-$U$4)+$U$4. My question is, is how do you find the closest value in the table when compared to the random value? Returning the closest match (percentage) is ideal and the table's values will change whenever the teams change. Eventually, I am trying to return the respective column and row values (goals for each team), but this is step 1 and haven't been able to figure it out yet - even with index and match. Feel like it should be fairly straightforward...
You may benefit from SUMPRODUCT and array formula to get closes match and goals values in rows and section. Just as example:
The upper table would be your data. The bottom table is just to check it it works, you can delete. This bottom table is just an absolute value of cell minus your rand. The minimun one is highlighted in green and that's the closest match. Notice how the formulas get the position of that match and the goals values:
Formula to get ROW VALUE:
=SUMPRODUCT(--(ABS(H4:R14-U6)=MIN(ABS(H4:R14-U6)))*G4:G14)
Formula to get COLUMN VALUE:
=SUMPRODUCT(--(ABS(H4:R14-U6)=MIN(ABS(H4:R14-U6)))*H3:R3)
Both of this formulas are array formulas, so to introduce them yo must press CTRL+ENTER+SHIFT or they won't work!
To get the closest match is just INDEX classic formula (we add +1 due to goals indexed as 0,1,2...):
=INDEX(H4:R14,U9+1,V9+1)
See it working!:
I've uploaded the file in case you want to check the formulas:
https://docs.google.com/spreadsheets/d/1wV8bn6B-jZ4jCxAonGdWFMluAEybzwkA/edit?usp=share_link&ouid=114417674018837700466&rtpof=true&sd=true
Please, notice this will work properly as far as there is a single closest match. If by any case two cells are both closest match, formula will return incorrect result.
And remember, as I said before, second table is just to explain the solution, you can delete it and everything will work.
You could create a 2nd table where you calculate the absolute or squared difference between your Poisson table values and the random value.
Then you can simply check for the smallest value in the 2nd table.
In your example, the 2nd table of differences could be created with the formula
=ABS($H$4:$R$14-$U$6)
Let's assume that this 2nd table is just below the 1st table, i.e. in H16:R26
Then the smallest value in this 2nd table is obtained by
=SMALL($H$16:$R$26,1)
from there you can get the row number through
=SUM(($H$16:$R$26=SMALL($H$16:$R$26,1))*($G$4:$G$14))
and the column number through
=SUM(($H$16:$R$26=SMALL($H$16:$R$26,1))*($H$3:$R$3))
Then, to find the closest match in the original table, you can use the INDEX() function and refer to the row and column calculated in the previous step.
You can of course skip all the intermediary steps and write everything into a single formula:
=LET(
table,$H$4:$R$14,
diff,ABS(table-$U$6),
closest,SMALL(diff,1),
closest_row,SUM((diff=closest)*SEQUENCE(ROWS(table))),
closest_col,SUM((diff=closest)*SEQUENCE(1,COLUMNS(table))),
INDEX(table,closest_row,closest_col)
)
Which looks like this:
Note: the last formula uses dynamic arrays and functions only available Excel O365.
Related
I am trying to pull data that has a vertical and horizontal lookup. The Vertical lookup provides the product that I'm trying to match and the horizontal lookup is for the dates. I have this lookup working across two sheets. It seems to be working okay, except that lookup for some reason pulls the value beneath the right value. This is really weird. Can someone please take a look at the formula and let me know what the issue might be?
$E59 - contains the lookup value - Forecast2 column A contains the data that would match with $E59. The main page $N$1 contains the date, and $G$4:$O$4 - in Forecast2 contains the date headers, whereas $G$5:$O$52 - contains the actual data.
My formula currently performs the lookup, but instead of bringing in the right value, it brings in the value beneath the right value. To give an example Row 5 in the Forecast2 sheet is the match that $E59 corresponds to, yet for some reason it's giving me the value from Row 6. If I then change the value of $E59 to match with what row 6's value is - the formula produces the value for row 7?
=XLOOKUP($E59,Forecast2!$A$4:$A$51,XLOOKUP('Main Page'!N$1,Forecast2!$G$4:$O$4,Forecast2!$G$5:$O$52))
Actually, your ranges are wrong. To correct it, you need put your values in A5:A52 and then refer to A5:A52 in place of A4:A51. Hence, your formula would become
=XLOOKUP($E59,Forecast2!$A$5:$A$52,XLOOKUP('Main Page'!N$1,Forecast2!$G$4:$O$4,Forecast2!$G$5:$O$52))
Another method is apply an offset of -1 but it is always better to fix the source rather than the result.
I am trying to achieve this in a table in Excel:
https://exceljet.net/formula/running-count-of-occurrence-in-list
So, counting each item in the list in an ordered sequence:
(I want it for Red and Green too, of course)
If I however convert it to a table, and add something like these variants, then I get a total instead for each. Is there a way to achieve this in a table column? The only other answer I found to this was within Power Query, which I won't be using for this table:
=IF([#Color]="blue",COUNTIF([Color]:[#Color],"blue"),"")
=IF([#Color]=[#Color],COUNTIF([Color]:[#Color],[#Color]),"")
=IF([#Color]="blue",COUNTIF([#Color],"blue"),"")
=IF([#Color]=[#Color],COUNTIF([#Color],[#Color]),"")
You can use INDEX() to refer to the range at hand per row:
Formula in B2:
=SUM(--(INDEX([Color],1):[#Color]=[#Color]))
Meaning:
INDEX([Color],1) - Always refer to the first row in the "Color" column;
: - Continue creating a valid range reference;
[#Color] - Refer to the current row/value.
=[#Color] - Match the above structure against the current row/value.
-- - Turn the TRUE/FALSE array into 1/0 values.
SUM() - Sum the given array to a total.
Note, the website you have tagged is quite handy, they also have exactly what you are after covered on another page. See this.
Also, I guess this needs to be CSE-entered in pre-365 versions of Excel.
I have been trying to make a form for some of my team members who are not that computer literate, and I essentially want to make it click and go. I thought I could do it...but alas I am not as good with nesting functions as I thought I was.
I have this spreadsheet where I want to put data into the yellow cell. On the next sheet I have the below table. What I want to do is use a formula to fill H4 with the "Request Branch's" Account Number. Now, I have currently filled the cells with information. They, in fact, have drop down options - which are pulled from the Account List table. As a result the value in H4 will continually change based on the needs of the user - but must be within the confines of the Account List Table.
What I have tried is here and enter link description here. I keep getting result of #Value, or N/A. I can't figure out what I am doing wrong. I know that I need to nest the SUMIFS withing VLookUp, but I am not sure as to why it won't work.
I'm providing you with two possible solutions.
1) The first one uses the SUMPRODUCT function. You may not have seen this kind of notation before.
When ranges are multiplied by each other like so (B3:B8=G3)*(C3:C8=G4) they are actually turned into boolean arguments. If you highlighted this part of the code and pressed F9 it would look like this: {0;0;0;0;1;0;0}. This is an array where TRUE for both criteria meet. So our Branch is "A" and our Carrier is "F". In the rest of the cases either or both are false resulting in zeroes.
Now if you multiply this array by the range with account numbers, obviously the only number remaining will be the one multiplied by 1 and so you have the answer however keep in mind that as you are multiplying if the account is not a number the function will fail!
2) This is why we have a second method using =INDEX() and =MATCH() functions.
To overly simplify this - the INDEX function grabs contents from an array at a specified position (row and column), while the MATCH function gets the position of an item in an array.
The idea with using ranges as multiple criteria is the same as in the first example, however this time when we get our array of zeroes and ones {0;0;0;0;1;0;0} we use the match function to find at which position our criteria cross (as seen on the screenshot it's the 5th position, as it's in the 5th row of the entire column D, the match function searches the {0;0;0;0;1;0;0} array for a 1 and returns its position in the array) and so this is our ROW.
Knowing the position of the contents we searched for we use the INDEX function to grab the contents of the cell in that position so =INDEX(D2:D8,MATCH(1, INDEX((B2:B8=G3)*(C2:C8=G4),0),0)) is actually =INDEX(D2:D8, 5) meaning that the INDEX function grabs contents of the 5th row from the range D2:D8 which is cell D6.
The green boxes are just there to show the instance where both of our criteria are met (cross).
Please try this formula.
=INDEX(Table1[Account],SUMPRODUCT((Table1[Branch]=F$3)*(Table1[Carrier]=F$4)*ROW(Table1[Account]))-1)
Note that you may have to adjust the final -1. This is because the indexed table starts in row #2 and the SUMPRODUCT function returns a sheet row number. If your table would start in a different row the difference between the sheet row and table row would be larger. It must be adjusted here. Or you might work with sheet references (named ranges) and require no adjustment at all.
I have a sheet with transactions. Each txn has an airport and an amount of fuel pumped. I have a second sheet with a list of locations, each row of which has min and max values for fuel bands (e.g, 1-500, 501-1000, min/max stored in separate columns), and each each of which have a price (for fuel per gallon).
I need to use the values per row in the first spreadsheet to search the second spreadsheet for a match on airport (ICAO code), greater than bottom of band, and less than top of band, and then return the unit price of fuel. The catch is that I can have multiple matches, and I need the smallest/lowest value.
I have some familiarity with Index/Match multi criteria arrays. So, I wrote the following and tried it:
=INDEX(FuelPrices!$D$2:$D$3398,MATCH(1,(FuelPrices!A:A=H2)*(FuelPrices!B:B>=N2)*(FuelPrices!C:C<=N2),0))
Where "Fuel" is my first sheet and "FuelPrices" is the sheet I'm looking up the values in. No matter WHAT I do it throws an #NA error. So, I figured maybe the problem was I was returning an array? I tried this:
=INDEX(FuelPrices!$D$2:$D$3398,SMALL(MATCH(1,(FuelPrices!A:A=H2)*(FuelPrices!B:B>=N2)*(FuelPrices!C:C<=N2),0),1))
Figuring it would give me the smallest value from the returned array. No go. I've tried some other tricks (using another Index function around the match) and nothing seems to work.
Basically I just want to get the function to return the lowest matching value for the provided criteria.
The short answer is that the < and > are the wrong way round. This does give an answer
=INDEX(FuelPrices!$D$2:$D$10,MATCH(1,(FuelPrices!$A$2:$A$10=H2)*(FuelPrices!$B$2:$B$10<=N2)*(FuelPrices!$C$2:$C$10>=N2),0))
if entered as an array formula using CtrlShiftEnter
I have changed all ranges to a small number of rows for testing purposes.
FuelPrices sheet
Fuel sheet
If you do want to find the smallest subject to the same conditions, you don't need index but can use small (or min)
=SMALL(IF((FuelPrices!$A$2:$A$10=H2)*(FuelPrices!$B$2:$B$10<=N2)*(FuelPrices!$C$2:$C$10>=N2),FuelPrices!$D$2:$D$10),1)
Or if you prefer you can use Aggregate (non-array formula)
=AGGREGATE(15,6,FuelPrices!$D$2:$D$10/((FuelPrices!$A$2:$A$10=H2)*(FuelPrices!$B$2:$B$10<=N2)*(FuelPrices!$C$2:$C$10>=N2)),1)
I am working on a statistical model where we use sumproduct to generate forecast values by multiplying coefficients in one table with variables in another. Right now it is being done manually and that is taking time. I would like to automate it but I'm not able to figure this out.
We are using concatenate to identify different rows to use for vlookup. The variable columns are the same in number for both tables. I need to multiply each variable cell respectively in both tables and sum them, hence sumproduct.
this is what I am trying to do
Forecast model 1 sales for product A in phones in USA = sumproduct([variables by year from table 1 for USA for phones], [Variables for USA phone product A model 1 from table 2] )
I hope someone can help me.
Proof of Concept
You will need to update the references to suit your spreadsheet table locations.
In cell E21 use the following and copy right and down as required:
=SUMPRODUCT(INDEX($G$3:$I$12,MATCH($B21&$A21&$C21,$A$3:$A$12,0),0),INDEX($F$15:$H$18,MATCH($A21&$C21&$D21&MID(E$20,16,1),$A$15:$A$18,0),0))
This process was simplified because you had a unique ID tag on each of the previous two tables that could be built from the information in the third table. If you ever get into double digit forecast models the MID() function part of the formula will need to be modified. The 16 in the mid function refers to the character location of the number in the forecast model sales header name in Table 3. As such you either need to keep that header format exactly the same or modify the position of the number in the MID() function.
UPDATE 1
Explanation of Formulas
The following formulas were used in this solution:
SUMPRODUCT
INDEX
MATCH
MID
Concatenate
I will start with the assumption that you already understand sumproduct() as you were already using it before you ran into your problem. One thing to note about sumproduct is that it causes array like calculation to occur on the portion within it brackets. In this case we fed it two ranges of equal size. The difficult part was more an issue of determining those ranges.
Using your ID columns as a lookup row we used the match() function to determine which row to use. For the first set of variables we used the following to determine which row to look in:
=MATCH($B21&$A21&$C21,$A$3:$A$12,0)
Match is made up of three arguments inside the brackets:
MATCH(what to look for, where to look, type of match)
What we need to look for in table is a concatenation of various cells in Table 3 to build the ID in Table 1. It could have been written using the full formula:
=CONCATENATE($B21,$A21,$C21)
but the short form using & was used instead:
=$B21&$A21&$C21
Once we had what to look for we needed the range of where to look and supplied the ID column from table 1:
$A$3:$A$12
This now leaves the third and final argument of what type of search to perform. An exact match seemed to be the most appropriate match to perform so the value of 0 was supplied. What match returns is the row within the supplied range. It is relative to the range supplied and not the actual row in the spreadsheet. If it cannot make a match it will return an error instead of a row number.
Now that we know what row we want, we can use this information with the INDEX() function. The INDEX() function is made up of 3 arguments as well with the third argument being optional depending on if a 1D or 2D range is being indexed:
INDEX(Range to work with, 2D Row or 1D Position reference, 2D Column reference)
IN the case we are dealing with for the first table, the range to work with was your list of variables:
$G$3:$I$12
This is a 2D range. As such we need to tell INDEX() both what Row to look in as well as which Columns to look in. For the row to look in, we used the previously discussed MATCH() function. Since we want all columns and not just a specific column we use the value of 0. If Match returns an error, or if a number greater than the number of rows or columns selected is supplied, INDEX() will return an error. Based on the information discussed, the index function would look like:
=INDEX($G$3:$I$12,MATCH($B21&$A21&$C21,$A$3:$A$12,0),0)
You can try entering the above in a cell but it will give you an error. if you select three adjacent cells in the same row and use CONTROL+SHIFT+ENTER when entering the formula, Excel will add {} around the formula and it will be an array formula and should show you the three variables being used.
The same process as described above can be used for determining the second range of variable from Table 2. The only difference here is that the forecast model number was not in a column of its own but instead in the header row surrounded by text. As such the MID() function needed to be used to go into the header row, bypass the surrounding text and pull the model number out so it could be used as part of the CONCATENATION() used for the "what to look for" in MATCH():
=MID(E$20,16,1)
The MID() function work again with three arguments:
MID(Text to look in, which character to start at, how many characters to pull)
So in this case we are looking at the header in E20. Note the lock $ on the row number so the formula is always looking in row 20 no matter how far down it gets copied. It is then going to the 16th character. In this case the character "1" and pulling 1 character. If the header had just been 1 and 2, there would be no need for the MID function and the cell (with proper lock) could have been used.