I need to find the average of 8 last (rightmost, from right to left) numeric cell values in a row that meet simple criteria of >= 0, ie. zero or positive numbers from rows that contain a mix of zeroes, and negative and positive values. In other words, I need to find the 8th cell reference from all cells containing 0 or higher counting from the end of the row backwards.
Example row:
1.6425 0.6233 5.2899 4.4372 2.0356 3.9796 1.5306 3.8344 0 -1 -1 3.8294 -1 3.0957 0 3.7572 -1
Expected result:
2.50
(3.7572 + 0 + 3.0957 + 3.8294 + 0 + 3.8344 + 1.5306 + 3.9796) / 8
I solved this cleanly using AVERAGEIFS and adding only one supplementary row A2:Q2 to mark just the 8 cells required. This extra row counts backwards from the end of the row, iterating by one from the previous count (next cell to the right) only if the cell above in row 1 is not less than 0, with the formula =IF(A1<0,B2,B2+1) copied throughout row A2:Q2. This then acts as criteria2 for the main formula i.e. use the first 8 cells from the right with a value >=0.
Then it's a simple =AVERAGEIFS(A1:Q1, A1:Q1, ">=0", A2:Q2, "<9") in cell C4 to get the result. C5 is a simple manual test against the calculated result.
Here's the Excel file: https://dl.dropbox.com/u/4974539/averageifs_tweak.xlsx - and a screen shot:
I solved your problem but with plenty of auxiliary columns. In the following I assume you have your data in columns A to Q, starting in row 2
On the first row, put letters A to J in columns T to AC
On the first data row
2.1 Put the forumula =ROW() in column S
2.2 Put array formula (press Shift + Ctrl + Enter when entering it) =SUM(IF(INDIRECT(T$1 & $S2 & ":Q" & $S2,TRUE)>=0,1,0)) to column T and copy it right all the way to column AC
2.3 Enter array formula =INDEX($T$1:$AC$1,MATCH(8,T2:AC2,0)) in column AD
2.4 Finally, put array formula =SUM(IF(INDIRECT(AD2 & S2 & ":Q" & S2) >= 0, INDIRECT(AD2 & S2 & ":Q" & S2), 0))/8 to column AE, this is the result you want
You can copy the row with formulas down to every row with data
This is how it looks in my Excel:
What it does:
in column S is the current row -- we need it for the INDIRECT function, because ROW() does not work in INDIRECT in array functions.
in columns T - AC we count the number of columns in the right side of the current row of data that are positive or zero, starting in different columns -- their letters are on the first row. The rightmost column where we can start is J, otherwise there would not be
8 values.
in column AD we match number 8 and from the first row we get the column where we have to start the range for averaging
finally, in column AE we use INDIRECT to create the reference to the range we want, sum all the numbers that are >= 0 and divide by 8
Related
In excel, I have a column of about 30,000 entries. I want to take that column and create a new one where the first entry will be the average of the first 4 entries in the original column. The 2 entry in the new column will be the average of the next 4 entries of the original column (from 5-8), so on and so forth. The new column then will therefore have 1/4 of the the size of the original column. How can you do this with excel?
In the image you see the N column from where I want to calculate the averages. In the Q column you see the average of the first 4 values of the N column. I want to extend the Q column so the second entry would be the average of the next 4 values (from 5th to 8th values) and so on and so forth for the remainder of the N column. As said, the Q column will therefore have at the end 1/4 of the size of the N column.
Try below formula.
=SUM(INDIRECT("N" & ROW()*4-3 & ":N" & ROW()*4))/4
ROW()*4 this will multiply every row by 4 means will create a series like 4, 8, 12 ... Now ROW()*4-3 will generate 1, 5, 9 ...
So, by this part of formula "N" & ROW()*4-3 & ":N" & ROW()*4 we will get N1:N4, N5:N8, N9:N12 and so on. INDIRECT() formula will redirect those ranges for SUM() formula and SUM formula will give you summation of of every 4 row data. Finally dividing by 4 will give you average.
#harun24hr has probably posted the right answer, but an alternative solution could be to do the following:
Merge 4 cells in the column you wnat to show the average and then calculate the average eg:
=AVERAGE(A1:A4)
I can't seem to find anything similar that's already been asked (they all relate to incrementing row numbers rather than columns)
I'm looking to drag a formula across horizontally and have the columns increment by 2
E.g. B1-A1, D1-C1, F1-E1...
Thanks!
You'll need to have a value in cell A1 and B1 for the following to work.
For my testing I put the number 1 in A1 and B1.
Try this in Cell C1:
=IF(MOD(COUNT($A$1:B1),2)=0,COLUMN(B1),IF(B1<>A1,B1,A1))
Here's what you should see when you drag that formula across:
A B C D E F G H I J K L M N
1 1 2 2 4 4 6 6 8 8 10 10 12 12
And this is what the formula does:
The MOD(COUNT() part of the formula counts the cells to the left of it, and if they are a multiple of 2, the value changes.
I've left the value to change to (the 'new' value) as the COLUMN() number for the cell before, just for example's sake. but you can change this part.
The last IF statement at the end checks if the cell before is equal to the cell before that, (eg. Is CELL C1 equal to CELL B1) and if they are not equal, it will give the cell before as a value (the 'copy' value).
I need to make a formula that gives you the truth table for a variable number of columns.
Example
The current recommended answer did not work for me. For a simpler method, I'd recommend the following formula:
=IF(MOD(FLOOR((ROW()-ROW(TopRight))/(2^(COLUMN(TopRight)-COLUMN())), 1),2)=0,0,1)
Where TopRight is the top right cell of the truth table.
For instance, if you're creating a truth table with 8 entries that starts in A3, replace TopRight with $H$3, then drag the formula across and down.
A basic explanation of what's going on: In truth tables, the rows alternate 1 or 0 every 2 ^ n number of rows, where n is the the number of columns that the given column is away from the rightmost column.
Replace the FirstCell with a static reference to the cell that contains the first 2^1 value e.g. $D$1 for a 4-bit table (16 values) and autofill to the rest of the grid (in the example A1:D16)
=IF(MOD(ROW()-ROW(FirstCell),POWER(2, ((COLUMN() - COLUMN(FirstCell)) * -1) + 1)) >= (POWER(2, ((COLUMN() - COLUMN(FirstCell)) * -1) + 1) / 2),1,0)
The logic behind this is:
If the current row modulus 2 power current column (* -1 as the first value is in the last column and + 1 because it starts from 0) is greater or equal to half of 2 power current column, put the value as 1, else put the value as 0.
The other answers might make Boole sad. This one aims to be more boolean.
You need to populate the first row (2) with 0's
For the LSB column (D) - Invert:
=NOT(D2)*1 (formula for cell D3, copied to D4:D17)
That will invert the value from the row above. The *1 numification is necessary to avoid seeing TRUE or FALSE
For all other columns - Add:
=XOR(AND(D2:$D2),C2)*1 (formula for cell C3, copied to all cells A3:C17)
For an ADD function, you want to XOR the value above in the column with the result of ANDing all the bits in all the columns to the right of it. (In other words: if all the bits to the right of the bit above are 1, then you should flip the value from the bit above. This ADD formula works for any number of columns.)
The AND range is referenced to one row up and one col right, to the $D LSB column, also one row up. So the $D anchor for the LSB column allows copying to any other column
Again, *1 is used for numification of the resulting TRUE/FALSE
Here's a Microsoft 365 one-liner:
=TRANSPOSE(LET(n,5,m,2^n,x,SEQUENCE(n,m,0),y,FLOOR(x/m,1),z,FLOOR((x-y*m)/2^(n-1-y),1),MOD(z,2)))
n is the number of columns needed, m then stores the length of each column.
The formula finds the row of x and stores the value in y, and then successively halves each row into the correct format, and outputs the result mod 2 to produce the truth table set of inputs.
TRANSPOSE is used because SEQUENCE places the numbers left-right, top-bottom.
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
.....
remember the numbers are only 0 or 1.
for column D: D2=1-D1
for column C: C2=IF(D1=1,1-D1,D1)
for column B: B2=IF((C1=1)*(D1=1),1-B1, B1)
.....
After did this, copy the numbers without formulas for your truth table to avoid Excel calculation.
I have a table like this:
Length 4
year 1 2 3 4 5
A 100 400 300 200 400
B
And in column B I want a sum of A from the past [length] years. For this I figured I needed an OFFSET, so my function is (for year 2):
=SUM.IF(OFFSET(B3;0;0;1;-B1);">0")
The if statement is used so it doesn't give an error when it reaches the edge of the table, but for years 2 and 3 the OFFSET range is outside of the worksheet so it doesn't work. How can I specify a condition that it just doesn't sum anything that isn't on the worksheet?
In A2:
=SUM(INDEX(1:1,COLUMNS($A:A)):INDEX(1:1,MAX(1,COLUMNS($A:A)-3)))
Copy to the right as required.
Regards
Ok, it was hard to decypher the question:
When you ask column B, I guess you mean row 4, right?
You don't need SUMIF, because SUM doesn't count empty cells or cells
with non-numeric value.
The reference to the length value should be absolute, so it doesn't
change as you copy the formula:
$B$1
OFFSET's Width value cannot be negative, rather have the Cols value =
-[Length]:
OFFSET(C3;0; -$B$1...
(Now you are referencing 4 columns left to C3)
Make sure it is not out of the worksheet by not letting more than the [column number of the given cell minus 1] be referenced left from the cell:
OFFSET(C3;0; -MIN(COLUMN(C3)-1;$B$1)...
That is the starting point of your range to sum; you should sum it
up to recent year's value. So the correct formula in C4 is:
=SUM(OFFSET(C3;0;-MIN(COLUMN(C3)-1;$B$1)):C3)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a table in excel, in the example below each number represents a cell:
11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
I would like to convert this table to a text file that looks like this:
11 12
13
14
15
21 22
23
24
25
31 32
33
34
35
I am aware of the transpose function and a table to text but I can't seem to achieve what I illustrated above.
Using a simple VBA is efficient to create the actual file.
This code dumps data from the range from A1 to the last used cell in column E of the activesheet, to a file C:\temp\dummy.txt
Please change your path to suit
Sub RipData()
Dim X
Dim lngRow As Long
Dim lngCol As Long
Dim objFSO As Object
Dim objTF As Object
X = Range([a1], Cells(Rows.Count, "E").End(xlUp))
Set objFSO = CreateObject("scripting.filesystemobject")
Set objTF = objFSO.createtextfile("C:\temp\dummy.txt")
For lngRow = 1 To UBound(X, 1)
objTF.writeline X(lngRow, 1) & vbTab & X(lngRow, 2)
For lngCol = 3 To UBound(X, 2)
objTF.writeline X(lngRow, lngCol)
Next
objTF.writeline
Next
objTF.Close
End Sub
I usually apply a combination of ROUND, MOD, and OFFSET to turn a tabular set of data into a single column. This problem has the added wrinkle of wanting to put the second number in a group in a column to the right while skipping that number in the first column. And you want to put place a spacer row between each group of numbers. Both of these requirements make for more complicated than usual formulas.
For the first column, beginning in cell A5, or in another cell in column A the row of which is an even multiple of 5, use the following formula,
= IFERROR(
OFFSET(
$A$1,
ROUNDDOWN( ROW(A5) / 5 - 1, 0),
MOD( ROW(A5), 5) + (MOD( ROW(A5), 5) <> 0)
) /
(MOD( ROW(A5), 5) <> 4),
""
)
and copying down the column. This assumes that the data rows begin in cell A1.
For the second column, beginning with the cell in column B to the right of the starting cell in column A, enter this formula,
= IFERROR(
OFFSET($A$1,
ROUNDDOWN( ROW(B5) / 5 - 1, 0),
MOD( ROW(B5), 5) + 1
) /
NOT( MOD( ROW(B5), 5) > 0),
""
)
again copying it down.
How the formulas work
Both the column A and the column B function are elaborations of OFFSET, which takes as its arguments a starting address, the number of rows down (or up) its result range will begin, and the number of columns to the right (or left) that the range will. (It also takes two more arguments, which are the width and the height of the range to return. Since we're only concerned with single cells, we can leave these two arguments out.)
For example, the row calculation for column A uses the expression
ROUNDDOWN(ROW(A5)/5-1,0).
In cell A5, this formula resolves to (5/5 - 1) or 0, with no rounding needed. So, the row offset is 0 from A1, which makes sense because the A5 formula is processing the first row of data.
In cell A6, the formula becomes 6/5 - 1, or 1.2 - 1, or 0.2, which rounds down to 0, again what we need since we're still grabbing numbers from row 1.
This continues until cell A10, when we get 10/5 - 1, or 1. We're finished with the first row of data (which had an offset of 0 rows from a1) and now move on to the second. The value of the row offset will continue as 1 up to cell A15, when it will go up by 1 again.
The calculation of the column offset is a bit trickier:
MOD(ROW(A5),5)+(MOD(ROW(A5),5)<>0))
The first term is MOD(ROW(A5),5). In cell A5, that becomes MOD(5, 5), with a result of 0 since the integer remainder of 5 / 5 is 0. Again, makes sense--the column offset of 0 from cell A1 means the we will pick up the value in column A. In cell A6, we've got MOD(6, 5), for a column offset of 1. This means the value in A6 will come from column B.
But we don't want that: the value in column B of each data row is supposed to be shown in column B of the result range. We need to skip from column A to column C to get the next value for column A of the results.
Hence the second term (MOD(ROW(A5),5)<>0)). This evaluates to TRUE for every row that is not an even multiple of 5--these are the rows that show a (result) value in column A and column B. TRUE evaluates to 1 when used in an arithmetic expression. So, we are adding 1 to the column offset when the formula is in rows 6, 7, 8, 9, 11, 12, etc., thereby skipping over column B of the data row.
Finally, the divisor (MOD(ROW(A5),5)<>4). This expression will evaluate to TRUE (or 1) when the row the formula is in does not have a remainder of 4 when divided by 5. That means it evaluates to FALSE or 0 only when the formula is in rows 9, 14, 19, etc.
These in fact are the rows for which we want a space between the groups of numbers. The purpose of this divisor is to produce a formula error when the formula is in those rows. We then catch that error in the IFERROR function that encloses the entire formula, and the output of the formula becomes "" -- the empty string.
I won't go through the column B expression, which uses the same kind of maneuvers to pick up the second value in each data row and show it beside the first values.
For convenience in copying and pasting to your worksheet, here are the unformatted versions of the formulas:
Cell A5 Formula: =IFERROR(OFFSET($A$1,ROUNDDOWN(ROW(A5)/5-1,0),MOD(ROW(A5),5)+(MOD(ROW(A5),5)<>0))/(MOD(ROW(A5),5)<>4),"")
Cell B5 Formula: =IFERROR(OFFSET($A$1,ROUNDDOWN(ROW(B5)/5-1,0),MOD(ROW(B5),5)+1)/NOT(MOD(ROW(B5),5)>0),"")