I am trying to build a spreadsheet that keeps track of my inventory. I want to use the First In First Out approach and need the formula to solve the following problem. I want to subtract the value 16 from the list of stocks over multiple rows.
Value= 16
Column A --> Column B
10 0
5 0
2 1
3 3
12 12
delete everything in B column and use this ArrayFormula like:
=ARRAYFORMULA(
IF(IF(A4:A="", ,{B1; (SUMIF(ROW(A4:A), "<="&ROW(A4:A), A4:A)-B1)*-1})>A4:A, 0,
IF(IF(A4:A="", ,{B1; (SUMIF(ROW(A4:A), "<="&ROW(A4:A), A4:A)-B1)*-1})>0, A4:A-
IF(A4:A="", ,{B1; (SUMIF(ROW(A4:A), "<="&ROW(A4:A), A4:A)-B1)*-1}), A4:A)))
Sample below:
Subtract: B2 = number [16]
Subtract: B3 = formula =B2-A2. Copy down.
Out: C2 = formula =IF(B2>A2,0,IF(B2>0,A2-B2,A2)). Copy down.
Related
I have data like:
Folder Replied Complied
1 testing 1 1
2 /complete/ 0 1
3 none 1 1
4 Incomplete 0 1
5 complete// 0 0
6 Incomplete 1 0
7 ABCcomplete 1 1
I like a measure to calculate the average of Complied (sum divided by count), only where Folder contains the string complete AND Replied is 0 (both conditions simultaneously).
Therefore rows 2, 4, 5 should be used in the count, resulting in 0.66... (1 + 1 + 0)/3
i've tried several things but the formula either results in an error, or returns the wrong result
i.e.
Measure = CALCULATE (
Average( [Complied]),
CONTAINSSTRING([Folder],"complete") && [replied] = 0
)
DAX is very confusing to me. Thanks in advance
edit:
I've seen examples like
`
= CALCULATE(AVERAGE([col]), CONTAINSSTRING([Folder],"complete") , [replied] = 0)
note the , instead of && but that doesn't work for some reason either. Neither does AND(condition1, condition2).
This dax measure should be the one you are looking for:
Measure = CALCULATE(AVERAGE(Sheet1[Complied]),
CONTAINSSTRING(Sheet1[Folder],"complete") && Sheet1[Replied]=0)
So how is it working?
ContainString to check about "complete", work like VBA instr function
&& in order to meet both condition
Calculate(method, expression) to filter all the value
Scorecard
You may first test with the following measure to check if statement is working in your case first:
IF(CONTAINSSTRING(Sheet1[Folder],"complete") && Sheet1[Replied]=0,"True","False")
Only three row is True here:
Is it possible to have a range of values in a cell so that Sheets understands it when calculating something?
Here's an example of the desired output:
A B C
1 Value Share Total sum
2 100.00 90-110% 90-110
Here, Total sum (C2) = A2 * B2 (so 100 * 90-110%), giving a range of 90-110.
However, I don't know how to insert this range of values into a cell without Sheets saying #VALUE!.
you will need to do it like this:
=REGEXREPLACE((A2*REGEXEXTRACT(B2, "\d+")%)&"-"&
A2*REGEXEXTRACT(B2, "-(\d+%)"), "\.$", )
for decimals:
=REGEXREPLACE((A40*REGEXEXTRACT(B40, "\d+.\d+|\d+")%)&"-"&
A40*REGEXEXTRACT(B40, "-(\d+.\d+%)|-(\d+%)"), "\.$", )
I was trying to use the Lua if function to represent the result with a “*” in front of the value under a circumstance using an if function.
fefec C2
--------------
2 *2
3 3
When the value in Column 1 (fefec) is smaller than 3, then it is shown as * with the value entered in C2. When the value in C1 is equal or greater than 3, it is shown the actual value in C2. The code I wrote is
(function()
if [f#fefec] < 3 then
return "*[f#fefec]"
else return [f#fefec]
end
end)()
But for the first row, I got *(2.000000000000), how can I get rid of these 0s after 2?
i am working through an EDX course on computer programming. I have come to this problem and dont know how to work through it. im not looking for an answer but more a point in the right direction.
so the question gives you a 2D array. two columns and N amount of rows. the N is the number of students. each column is the grade of first test and then the second is the grade of the second test. I am asked to find the root mean square of two seperate kids and compare them and then return a number based off the comparison. The question gives you this formula
RMS = (0.5×(midsem_marks2 + endsem_marks2))0.5
I know how to get the appropriate marks using array[index 1(firsttest)] etc and then how to compare them. However, i am clueless on how to write that formula. any help would be great. Thanks in advance.
code I have
float RMSi1 = sqrt(.5*((marksarray[index1][0]*marksarray[index1][0])+(marksarray[index1][1])*(marksarray[index1][1])));
float RMSi2 = sqrt(.5*((marksarray[index2][0]*marksarray[index2][0])+(marksarray[index2][1])*(marksarray[index2][1])));
if(RSMi1>RSMi2){
return -1;
}
if(RSMi1<RSMi2){
return 1;
}
if(RSMi1==RSMi2){
return 0;
}
I'm getting an error that the RSMi1 and 2 are not declared in the if statements
Input marksarray:
1 2
1 60 20
2 60 20
3 30 40
4 10 90
5 90 30
6 0 100
7 60 20
Ok guys, as requested, I will add more info so that you understand why a simple vector operation is not possible. It's not easy to explain in few words but let's see. I have a huge amount of points over a 2D space.
I divide my space in a grid with a given resolution,say, 100m. The main loop that I am not sure if it's mandatory or not (any alternative is welcomed) is to go through EACH cell/pixel that contains at least 2 points (right now I am using the method quadratcount within the package spatstat).
Inside this loop, thus for each one of this non empty cells, I have to find and keep only a maximum of 10 Male-Female pairs that are within 3 meters from each other. The 3-meter buffer can be done using the "disc" function within spatstat. To select points falling inside a buffer you can use the method pnt.in.poly within the SDMTools package. All that because pixels have a maximum capacity that cannot be exceeded. Since in each cell there can be hundreds or thousands of points I am trying to find a smart way to use another loop/similar method to:
1)go trough each point at a time 2)create a buffer a select points with different sex 3)Save the closest Male-Female (0-1) pair in another dataframe (called new_colonies) 4)Remove those points from the dataframe so that it shrinks and I don't have to consider them anymore 5) as soon as that new dataframe reaches 10 rows stop everything and go to the next cell (thus skipping all remaining points. Here is the code that I developed to be run within each cell (right now it takes too long):
head(df,20):
X Y Sex ID
2 583058.2 2882774 1 1
3 582915.6 2883378 0 2
4 582592.8 2883297 1 3
5 582793.0 2883410 1 4
6 582925.7 2883397 1 5
7 582934.2 2883277 0 6
8 582874.7 2883336 0 7
9 583135.9 2882773 1 8
10 582955.5 2883306 1 9
11 583090.2 2883331 0 10
12 582855.3 2883358 1 11
13 582908.9 2883035 1 12
14 582608.8 2883715 0 13
15 582946.7 2883488 1 14
16 582749.8 2883062 0 15
17 582906.4 2883317 0 16
18 582598.9 2883390 0 17
19 582890.2 2883413 0 18
20 582752.8 2883361 0 19
21 582953.1 2883230 1 20
Inside each cell I must run something according to what I explained above..
for(i in 1:dim(df)[1]){
new_colonies <- data.frame(ID1=0,ID2=0,X=0,Y=0)
discbuff <- disc(radius, centre=c(df$X[i], df$Y[i]))
#define the points and polygon
pnts = cbind(df$X[-i],df$Y[-i])
polypnts = cbind(x = discbuff$bdry[[1]]$x, y = discbuff$bdry[[1]]$y)
out = pnt.in.poly(pnts,polypnts)
out$ID <- df$ID[-i]
if (any(out$pip == 1)) {
pnt.inBuffID <- out$ID[which(out$pip == 1)]
cond <- df$Sex[i] != df$Sex[pnt.inBuffID]
if (any(cond)){
eucdist <- sqrt((df$X[i] - df$X[pnt.inBuffID][cond])^2 + (df$Y[i] - df$Y[pnt.inBuffID][cond])^2)
IDvect <- pnt.inBuffID[cond]
new_colonies_temp <- data.frame(ID1=df$ID[i], ID2=IDvect[which(eucdist==min(eucdist))],
X=(df$X[i] + df$X[pnt.inBuffID][cond][which(eucdist==min(eucdist))]) / 2,
Y=(df$Y[i] + df$Y[pnt.inBuffID][cond][which(eucdist==min(eucdist))]) / 2)
new_colonies <- rbind(new_colonies,new_colonies_temp)
if (dim(new_colonies)[1] == maxdensity) break
}
}
}
new_colonies <- new_colonies[-1,]
Any help appreciated!
Thanks
Francesco
In your case I wouldn't worry about deleting the points as you go, skipping is the critical thing. I also wouldn't make up a new data.frame piece by piece like you seem to be doing. Both of those things slow you down a lot. Having a selection vector is much more efficient (perhaps part of the data.frame, that you set to FALSE beforehand).
df$sel <- FALSE
Now, when you go through you set df$sel to TRUE for each item you want to keep. Just skip to the next cell when you find your 10. Deleting values as you go will be time consuming and memory intensive, as will slowly growing a new data.frame. When you're all done going through them then you can just select your data based on the selection column.
df <- df[ df$sel, ]
(or maybe make a copy of the data.frame at that point)
You also might want to use the dist function to calculate a matrix of distances.
from ?dist
"This function computes and returns the distance matrix computed by using the specified distance measure to compute the distances between the rows of a data matrix."
I'm assuming you are doing something sufficiently complicated that the for-loop is actually required...
So here's one rather simple approach: first just gather the rows to delete (or keep), and then delete the rows afterwards. Typically this will be much faster too since you don't modify the data.frame on each loop iteration.
df <- generateTheDataFrame()
keepRows <- rep(TRUE, nrow(df))
for(i in seq_len(nrow(df))) {
rows <- findRowsToDelete(df, df[i,])
keepRows[rows] <- FALSE
}
# Delete afterwards
df <- df[keepRows, ]
...and if you really need to work on the shrunk data in each iteration, just change the for-loop part to:
for(i in seq_len(nrow(df))) {
if (keepRows[i]) {
rows <- findRowsToDelete(df[keepRows, ], df[i,])
keepRows[rows] <- FALSE
}
}
I'm not exactly clear on why you're looping. If you could describe what kind of conditions you're checking there might be a nice vectorized way of doing it.
However as a very simple fix have you considered looping through the dataframe backwards?