Repeat each value a different number of times, in Google Sheets [duplicate] - excel

This question already has answers here:
Repeat each row N times in Google Sheets
(4 answers)
Closed 16 days ago.
This post was edited and submitted for review 16 days ago and failed to reopen the post:
Original close reason(s) were not resolved
Given a list of values and a number n for each value, is there a way to create a 1-dimensional list with each value repeating n times?
A
B
C
1
animal
# repeats
result
2
aardvark
3
aardvark
3
badger
0
aardvark
4
capybara
1
aardvark
5
duck
2
capybara
6
duck
7
duck
Ideally, this would be a single formula in C2.
I'm working in Google Sheets, but I'd be interested in Excel answers, too.
Note that this is different from questions like these, which have the same n for all values.

You can try either
=TOCOL(MAP(A2:A,B2:B,LAMBDA(a,b,WRAPROWS(a,b,a))),3)
OR
=LAMBDA(z,FILTER(z,z<>""))(FLATTEN(MAP(A2:A,B2:B,LAMBDA(a,b,IF(a="",,IFERROR(SPLIT(REPT(a&"|",b),"|")))))))

pretty much the same:
=INDEX(TRIM(TRANSPOSE(SPLIT(QUERY(
REPT(A2:A10&"♠", B2:B10), ,9^9), "♠"))))

Repeat Rows a Given Number of Times (Excel Formula)
Due to the poor performance of the XLOOKUP or XMATCH functions (23s on 10k rows), the superior MATCH function is used with the INDEX function (3s on 10k rows).
LET
=LET(Data,A2:A5,Repeats,B2:B5,
Both,HSTACK(Data,Repeats),Filtered,FILTER(Both,Repeats>0),
dData,TAKE(Filtered,,1),dStacked,VSTACK(dData,""),
rData,TAKE(Filtered,,-1),rSequence,SEQUENCE(SUM(rData)),
rStacked,VSTACK(0,rData),rScanned,SCAN(1,rStacked,LAMBDA(a,b,a+b)),
rIndexes,MATCH(rSequence,rScanned),
Result,INDEX(dStacked,rIndexes),Result)
If you prefer fewer variables:
=LET(Data,A2:A5,Repeats,B2:B5,
Filtered,FILTER(HSTACK(Data,Repeats),Repeats>0),
dStacked,VSTACK(TAKE(Filtered,,1),""),
rData,TAKE(Filtered,,-1),rSequence,SEQUENCE(SUM(rData)),
rScanned,SCAN(1,VSTACK(0,rData),LAMBDA(a,b,a+b)),
Result,INDEX(dStacked,MATCH(rSequence,rScanned)),Result)
Screenshot Formulas
F2 =HSTACK(A2:A5,B2:B5)
H2 =FILTER(F3#,B2:B5>0)
J2 =TAKE(H3#,,1)
K2 =VSTACK(J3#,"")
L2 =TAKE(H3#,,-1)
M2 =SEQUENCE(SUM(L3#))
N2 =VSTACK(0,L3:L5)
O2 =SCAN(1,N3#,LAMBDA(a,b,a+b))
P2 =MATCH(M3#,O3#)
Q2 =INDEX(K3#,P3#)
R2 =LAMBDA(Data,Repeats,LET(
Both,HSTACK(Data,Repeats),Filtered,FILTER(Both,Repeats>0),
dData,TAKE(Filtered,,1),dStacked,VSTACK(dData,""),
rData,TAKE(Filtered,,-1),rSequence,SEQUENCE(SUM(rData)),
rStacked,VSTACK(0,rData),rScanned,SCAN(1,rStacked,LAMBDA(a,b,a+b)),
rIndexes,MATCH(rSequence,rScanned),
Result,INDEX(dStacked,rIndexes),Result))(A2:A5,B2:B5)
S2 =LAMBDA(Data,Repeats,LET(
Both,HSTACK(Data,Repeats),Filtered,FILTER(Both,Repeats>0),
dData,TAKE(Filtered,,1),dStacked,VSTACK(dData,""),
rData,TAKE(Filtered,,-1),rSequence,SEQUENCE(SUM(rData)),
rStacked,VSTACK(0,rData),rScanned,SCAN(1,rStacked,LAMBDA(a,b,a+b)),
rIndexes,MATCH(rSequence,rScanned),
Result,INDEX(dStacked,rIndexes),Result))
Using the last formula, define a name e.g. RepeatSeq, and use the name instead:
=RepeatSeq(A2:A5,B2:B5)

Related

Dynamically sort list based off associated values with tie-breaker values

I'm trying to sort students based off frequency of participation. I have a table that is automatically generated totaling up how often a student has participated in the last few days.
I want it to do 2 things that I can't figure out.
I want it to ignore students that are at 0 removing them from the resulting rankings.
The first number is most important but I want it to reference the next value in the result of a tie.
Short example of table:
Andy - 1 1 2 3
Brad - 0 1 2 3
Cade - 1 2 3 4
Dane - 1 1 1 2
Desired result:
Cade - 1
Andy - 1
Dane - 1
The tie-breaker isn't that important and I figure I can have conditional formatting to remove children at 0, but I still can't seem to figure it out.
The closest formulas I have found in my searching are:
=INDEX($A$10:$A$9,MATCH(ROWS($C$1:C1),$C$1:$C$9,0))
This one doesn't work because it returns #N/A for pretty much all students who are tied.
=IFERROR(INDEX($C$1:$C$9,MATCH(SMALL(NOT($C$1:$C$9="")*IF(ISNUMBER($C$1:$C$9),COUNTIF($C$1:$C$9,"<="&$C$1:$C$9),COUNTIF($C$1:$C$9,"<="&$C$1:$C$9)+SUM(--ISNUMBER($C$1:$C$9))),ROWS($C$1:C1)+SUM(--ISBLANK($C$1:$C$9))),NOT($C$1:$C$9="")*IF(ISNUMBER($C$1:$C$9),COUNTIF($C$1:$C$9,"<="&$C$1:$C$9),COUNTIF($C$1:$C$9,"<="&$C$1:$C$9)+SUM(--ISNUMBER($C$1:$C$9))),0)),"")
I had this formula that can handle ties but it needs to be OFFSET but I don't know how since it is an array formula. Also, with both these formulas it reverses the ranks with the lowest values at the top. If anyone could assist me I would greatly appreciate it. I'm doing this so that I can give all students a chance to participate equally.
Use a helper column. In that column put the following formula:
=IF(B1=0,"n/a",SUMPRODUCT(B1:E1/10^(COLUMN(B1:E1)-MIN(COLUMN(B1:E1)))))
This will return a single number based on the rankings.
Then in your output column use:
=IFERROR(INDEX(A:A,MATCH(LARGE(F:F,ROW(1:1)),F:F,0)),"")
Then a simple VLOOKUP to return the first number:
=IF(I1<>"",VLOOKUP(I1,A:B,2,FALSE),"")

Count occurrences of strings just once per row in Google Sheets

I have strings of spreadsheet data that need counting by 'type' but not instance.
A B C D
1 Lin 1 2 1
2 Tom 1 4 2
3 Sue 3 1 4
The correct sum of students assigned to teacher 1 is 3, not 4. That teacher 1 meets Lin in lessons B and D is irrelevant to the count.
I borrowed a formula which works in Excel but not in Google Sheets where I and others need to keep and manipulate the data.
F5=SUMPRODUCT(SIGN(COUNTIF(OFFSET(B$2:D$2, ROW($2:$4)-1, 0), E5)))
A B C D E
2 Lin 1 2 1
3 Tom 1 4 2
4 Sue 3 1 4
5 1 [exact string being searched for, ie a teacher name]
I don't know what is not being understood by Google Sheets in that formula. Does anyone know the correct expression to use, or a more efficient way to get the accurate count I need, without duplicates within rows inflating the count?
So this is the mmult way, which works by finding the row totals of students assigned to teacher 1 etc., then seeing how many of the totals are greater than 0.
=ArrayFormula(sum(--(mmult(n(B2:D4=E5),transpose(column(B2:D4)))>0)))
or
=ArrayFormula(sum(sign(mmult(n(B2:D4=E5),transpose(column(B2:D4))))))
Also works in Excel if entered as an array formula without the ArrayFormula wrapper.
A specific Google Sheets one can be quite short
=ArrayFormula(COUNTUNIQUE((B2:D4=E5)*row(B2:D4)))-1
counting the unique rows containing a match.
Note - I am subtracting 1 in the last formula above because I am assuming there is at least one zero (non-match) which should be ignored. This would fail in the extreme case where all students in all classes are assigned to the same teacher so you have a matrix (e.g.) of all 1's. This would be more theoretically correct:
=ArrayFormula(COUNTUNIQUE(if(B2:D4=E5,row(B2:D4),"")))

SUMIF formula to find sum for dates today or earlier

so I have this table of salaries that I make (hypothetically):
A B C D
1 Date salary how_much_I_earned_so_far
2 total =SUM(salaries_until_today)
3 2017-10-1 5000
4 2017-11-1 5000
5 today-> 2017-12-1 5000
6 2018-01-1 5000
7 2018-02-1 5000
8 future.. 2018-03-1 5000
9 2018-04-1 5000
now I want to calculate on D2 the amount of money I have earned so far..
to do that, I want to sum up all the past salaries from C3 all the way down to C_x where x is the index of the line where today < B_x
so that raised me two questions
1) how do I select unknown index of cell? usually when I do formulas it looks like this =SUM(C2:C9) so how can I make the number 9 be variable?
2) can I create variable that depends on a number of lines of where a cell is smaller than a value? I know how to get the current day, its simply =TODAY() but now I want to compare it with all B's and find the index of line where its smaller than it.. how do I start?
I'm sorry if that's a weird question, I'm a programmer and its frustrating me that a simple thing that I could quickly solve by code cannot be accomplished in a sophisticated app such excel..
thanks.
=SUMIF(B:B,"<=" & TODAY(),C:C)

Excel formula to apply penalty column to ranking

I have thought long and hard about this, but I can't find a solution to what I believe is quite a simple problem.
I have a table of results, where sometimes someone will be given a penalty of a varying amount. This is entered into the penalty column (Col C).
I need a formula which checks if there is an entry into the penalty column and applies it, not only to that row, but to the number of subsequent rows which are affected, depending on the severity of the penalty.
I have tried to see if this is possible by referencing the penalty against the 'ROW()' function but have not been able to achieve the desired effect.
Col D shows the desired output of the formula.
Col E is included for reference only, to show the desired effect on each row.
Col A Col B Col C Col D Col E
Pos Name Penalty New Pos Change
1 Jack 1 0
2 Matt 2 0
3 Daniel 2 5 +2
4 Gordon 3 -1
5 Phillip 4 -1
6 Günther 6 0
7 Johann 3 10 +3
8 Alain 7 -1
9 John 8 -1
10 Gianmaria 9 -1
The big issue is, if someone is handed a big penalty, for example '10' then it affects the following ten rows. I can't work out how to include this variable logic...
I would be interested to hear the approach of others...
You need to use the RANK() function:
Excel RANK Function Examples
In a new column, add the penalty value to the original position, plus a small coeffieient depending on the original position (0.01 per increment perhaps) to move the penalised player below the original person at that position, then in the next column you can RANK() the new column of values (F in my case).
New value is therefore =A2+(IF(C2>0,C2+(0.01*A2)))
Rank is then =RANK(F2,F2:F11,1)
You can combine all the functions into one, but it's clearer to do it in separate columns at first.

Lookup multiple values in excel

Is there a way for excel formulas to look up multiple values in an 2d matrix for excel? For example:
sum(vlookup({2015,2016},Matrix,{2,4,6},False)) = 3 + 4 + 5 + 2 + 3 + 2
2014 1 3 7 11 9 2
2015 3 6 4 12 5 8
2016 2 1 3 99 2 6
I don't necessarily have to use the function vlookup but I prefer not having to use the same function multiple times then summing them since the list {2015,2016} could be quite long.
Put your search criteria in one cell each:
Then use this formula:
=SUMPRODUCT(ISNUMBER(SEARCH($A$1:$A$3,J1))*ISNUMBER(SEARCH(COLUMN($B$1:$G$3),K1))*$B$1:$G$3)
If you want to hard code the numbers then you can do it this way:
=SUMPRODUCT(ISNUMBER(SEARCH($A$1:$A$3,"2015,2016"))*ISNUMBER(SEARCH(COLUMN($B$1:$G$3),"2,4,6"))*$B$1:$G$3)
I like #ScottCraner's answer a lot, I just did it slightly differently, but using close-on the same tricks.
For me, I put the year values in as follows in column N:
N1 = 2015
N2 = 2016
And the columns I wanted to use for the look-up in column O:
O1 = 2
O2 = 4
O3 = 6
Then, I used the following (entered as an array formula - meaning you press CTRL+SHIFT+ENTER after putting it in):
=SUMPRODUCT(ISNUMBER(MATCH(A1:A3,$N$1:$N$2,0))*ISNUMBER(MATCH(COLUMN(A1:G3)-COLUMN(A1)+1,$O$1:$O$3,0))*A1:G3)
Again, Scott's answer is perfectly right, I just added in a different way to get to the same result.
Hope it helps you or someone else facing the same kind of challenge.

Resources