I'm trying to delete multiple consecutive and non-consecutive columns from a 80-column, 1-row cell array mycells. My question is: what's the correct indexing of a vector of columns in Matlab?
What I tried to do is: mycells(1,[4:6,8,9]) = [] in an attempt to remove columns 4 to 6, column 8 and 9. But I get the error: A null assignment can have only one non-colon index.
Use a colon for the first index. That way only the 2nd index is "non-colon". E.g.,
mycells(:,[4:6,8,9]) = []
MATLAB could have been smart enough to recognize that when there is only one row the 1 and : amount to the same thing and you will still get a rectangular array result, but it isn't.
Before getting the above VERY VERY HELPFUL AND MUCH SIMPLER answers, I ended up doing something more convoluted. As it worked in my case, I'll post it here for anyone in future:
So, I had a cell array vector, of which I wanted to drop specific cells. I created another cell array of the ones I wanted to remove:
remcols = mycells(1,[4:6,8,9])
Then I used the bellow function to overwrite onto mycells only those cells which are different between remcols and mycells (these were actually the cells I wanted to keep from mycells):
mycells = setdiff(mycells,remcols)
This is not neat at all but hopefully serves the purpose of someone somewhere in the world.
Related
A truncated version of my data is in the form shown in the screenshot below: three columns of 5 unique names. The names appear in any order and in any position but never repeat in a single row.
My goal is to create an array that contains the number of times Adam appears in each row. I can fill down the formula=countif(A2:C2,$I$2) in a new column, or if I write the array manually for each row, it looks like:
={countif(A2:C2,$I$2);countif(A3:C3,$I$2);countif(A4:C4,$I$2);countif(A5:C5,$I$2);countif(A6:C6,$I$2)}
Where cell I2 contains "Adam". Of course, this is not feasible for large data sets.
I know that arrays are effectively cells turned into ranges, but my main issue is that the cell I'm trying to transform already references a range, and I don't know how to tell the software to apply the countif down each row (i.e. I intuitively would like to do something like countif((A2:C2):(A99:C99),"Adam") but understand that's not how spreadsheets work).
My goal is ultimately to perform some operations on the corresponding array but I think I'm comfortable enough with that once I can get the array formula I'm looking for.
try:
=ARRAYFORMULA(IF(A2:A="",,MMULT(IF(A2:C="Adam", 1, 0), {1;1;1})))
So I'm having difficulties understanding fully how arrays works and when they are used by excel and specifically what happens in the background.
From reading the past few hours I understand that one of the reasons my Index Match doesn't work without array is simply because its a multicriteria Match that I use as below:
{=INDEX(D30:E36,MATCH(F33&G33,B30:B36&C30:C36),2)}
From what I understand the reason is that Match returns a {x,y} result which classifies it as an array formula. But considering the point is to get a row number, if the row I'm looking for is 5 then Match will return a {5,5} for row number for Index. And then Index interprets this as just 5? or what exactly happens in the background here?
Then I found an article which showed how to circumvent the array formula and not need ctrl+shift+enter as shown below. How does the below change things and what happens in the background?
=INDEX(D30:E36,MATCH(F33&G33,INDEX(B30:B36&C30:C36)),2)
The below is a an array SUM/COUNTIF formula which counts unique cells only which does not work without array brackets. Why is that and how does it work? It involves maths so I'm not sure.
{=SUM(1/(COUNTIF(A1:A5,A1:A5)))}
Thank you!
As shown in the attached image, I need to convert A2:D10 to the format of A12:E17. The 4 tables from F1 to AB12 are my experiments using if, match, and index. Same formula gets different results and it seems to be dependent on the row position of the tables. In My previous question, I was trying to pinpoint the problem to the if function.
What am I doing wrong here?
Thanks,
Lu
enter image description here
Again, as I said in your last question: The formula has not been array entered. Array formulas need to be confirmed with Ctrl-Shift-Enter.
Without that, the first array in the IF statement does not get resolved and the Match does not return the correct result.
Make use of the Evaluate Formula tool and step through the formula.
The merged cells don't help with the cell referencing. Unmerge the cells and fill in all the labels in row 1, then use this slightly amended formula and confirm it with Ctrl-Shift-Enter. Then copy across and down.
I hope that I get the English names of the functions right:
In D14 and following cells:
=INDEX($C$1:$C$5;MATCH(1;MMULT(($B$3:$B$10=$A14)*($A$3:$A$10=B$13);1);0))
The MATCH function tells which value (by number counted from the top) matches both conditions. The INDEX function returns this value from C1:C5.
I have a function that returns a matrix of information that I want to store in a cell, however no matter how I try this it keeps giving me various errors or the results are incorrect, my latest attempt is shown below:
bbag=[]
for j=3:100
bag=rand(randi([1 5]),randi([1 5]))%stand in for more complex function that normally returns between 1 and 4
[dontcare,y] = size(bag);
tbag={bag(1,1),bag(2,1),bag(3,1),bag(4,1),bag(4,1)}
for i=2:y
tbag=[tbag,{bag(1,i),bag(2,i),bag(3,i),bag(4,i)}]; %some kind of loop is probably required here
end
bbag=vertcat(bbag,tbag)
labels(i) = 1;
end
but this cannot handle when the data contains anything other than 4 data columns and if it does it only manages to append all the data on the same row not put it in it's own cell, any idea how to do this such that by the end I can ask for bbag(2,3) and then return a cell containing between 1 and 5 values? If I fix the sizes to be 4 then I instead get a 98-by-17 cell block (rather then 98x4x4 that I would expect). Any ideas?
In
bag=rand(randi([1 5]),randi([1 5]));
you create a random matrix with random size (i.e. random number of rows and columns). I don't know if the errors have anything to do with cell array creation; they have everything to do with the fact that you access e.g. row 3 from bag without making sure that you actually have 3 rows in it.
Also, check the doc for mat2cell for splitting a matrix into a cell array of heterogeneous-size matrices (if this is indeed what you're looking for).
This question is about how Excel's COUNTIF function treats different data types when used as an array formula.
There are lots of good posts out there detailing how to use COUNTIF for tasks such as extracting unique values from a list, for example this post. I've managed to use examples from this and other posts to solve specific problems, but I'm trying to get a deeper understanding of array formulas in order to adapt my formulas to new needs.
I came across a peculiar behavior of COUNTIF. In general, Excel seems to treat strings as "larger than" numbers, so that the following examples are valid:
Cell Formula Returns
=1<2 TRUE
="a"<"b" TRUE
="a">"b" FALSE
=1<"b" TRUE
Now, suppose range A1:A6 contains the following data set:
1
2
3
A
B
C
For each cell in this set, I want to check how many of all the cells in the set that are smaller than or equal to that cell (a useful technique in more complex formulas). I enter the following array formula in range B1:B6:
{=COUNTIF($A$1:$A$6,"<="&$A$1:$A$6)} (CTRL + SHIFT + ENTER)
Based on the examples above comparing numbers and strings (also illustrated in Column D below), I would expect the output shown below to look like Column C. However, the array formula returns the result shown in Column B, which suggests that strings and number elements are counted separately by arraywise COUNTIF.
Column A Column B Column C Column D
1 1 1 A1<"C" = TRUE
2 2 2 A2<"C" = TRUE
3 3 3 A3<"C" = TRUE
A 1 4 A4<"C" = TRUE
B 2 5 A5<"C" = TRUE
C 3 6 A6<"C" = FALSE
So the question is how to produce the output in Column C? (EDIT: Just to clarify, I'm specifically looking for solutions that make use of COUNTIF's array properties.)
Any insight into why arraywise COUNTIF apparently behaves differently than the single-cell examples would also be much appreciated.
NOTE: I've translated the examples from a non-English version of Excel, so I apologize in advance for any typos.
PS. For a background, I ran into this problem when I tried to build a formula that would both extract unique values from a list with possible duplicates, and sort the unique values in numerical/alphabetical order. My current solution is to do this in two steps. One solution for how to do it in one step is proposed here.
First of all, excellently laid-out question, and on an interesting topic to boot.
I also raised an eyebrow when I first came across this behaviour of the COUNTIF(S)/SUMIF(S) functions. In their defence, I suppose we could construct situations in which we actually want strings and numerics to be considered separately.
In order to construct your required in-formula array, you will need something like:
MMULT(0+(TRANSPOSE($A$1:$A$6)<=$A$1:$A$6),ROW($A$1:$A$6)^0)
though note that the necessary transposition will mean that any set-up which includes this construction will require committing with CSE.
Regards
The different behavior can easily shown if you compare
=COUNTIF($A$1:$A$6,"<=A")
with
{=COUNT(IF($A$1:$A$6<="A",1))}
The first will only get text values from $A$1:$A$6 because it is clearly text to compare and it is faster ignoring other values then. =COUNTIF($A$1:$A$6,"<=3") will only get numeric values from $A$1:$A$6 because of the same reasons. Even if the criterion would be a concatination with a cell reference, then the concatination would be the first process and would lead either to "<=A" or "<=3". So it is ever clear what to compare, text or numbers.
The second first needs an array of the comparisons, then performs the IF, gets so an array of 1 or FALSE and counts then. But the "A" could also be a cell reference. So it is not clear what to compare at the beginning and the first array has to compare all values in $A$1:$A$6.
So COUNTIF(S) and SUMIF(S) cant be used comparing mixed text and numeric data.
The solution is shown already by XOR LX.
Btw.: with your PS. For a background you should consider the following solution from an German Excel site: http://www.excelformeln.de/formeln.html?welcher=236.
In your linked example:
Formula in B2 downwards
{=INDEX($A$2:$A$99,MATCH(LARGE(COUNTIF(A$2:A$99,">="&A$2:A$99)+99*ISNUMBER(A$2:A$99),ROWS($1:1)),COUNTIF(A$2:A$99,">="&A$2:A$99)+99*ISNUMBER(A$2:A$99),0))&""}
In this solution the COUNTIF compares with >= so the biggest text or number will count lowest and so get the lowest position. All number positions are added with 99. So they are ever greater than all possible text positions. So we have a descended sorted array. Then, using LARGE, the list is created from the highest to the lowest position.
I doubt that countif is the right function for what you want to achieve here.
try this (ctrl+shift+enter):
={SUM(IF(A1>=$A$1:$A$6,1,0))}
You will get
1
2
3
4
5
6
PS: CountIf is an basically an array function internally. Using it in another array function results into multiple array functions and their behaviour becomes complex. Array functions are best used with clear logical path.
As tested in Excel 2013, you will only get 1 in all results instead of what was proposed in Column B.
Currently, in the function provided by you, countif cannot figure out which cell to compare to which cell. Array functions expand ranges and then perform the provided action. Therefore, it is comparing each cell to same cell and resulting into 1.
Try this FormulaArray in B1 then copy till B6:
=SUM(($A$1:$A$6<=$A1)*1)