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).
Related
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.
I am trying to filter an array to only include those values that are not within a set distance of a change in that array.
Here's my example:
The input array increases monotonically in steps. I want to zero out any of the input values from N rows above to N rows below any point where the value changes. Cell $B$2 holds this "window" value.
For example, cell A9 (value 11) is different from cell A8 (value 5), so I want to zero out values that come from any cells from A7 to A11 inclusive. That is from -N to +N relative the cell where the change occurs, where N=2.
I can achieve the required output with non-array functions, using intermediate calculation columns, but since I am processing a large number of columns it would save greatly on spreadsheet real-estate if I could construct a single array formula that operates on the range A4:A25, and uses cell B1 for the size of N. I am using the current Excel Beta, so I have access to LET and LAMBDA if needed.
I have tried various combinations, using SEQUENCE, but I run into the issue that LET (or indeed any array functions) seems to fail if they contain two SEQUENCE statements.
I am continuing to work on this, but if anyone wants to have a try, I would be most grateful!
UPDATE: This formula does the trick, but needs to be copied down:
=A4*IF(AVERAGE(OFFSET(A4,-($B$1+1),0,2*($B$1+1),1))<>A4,0,1)
So, while the suggestion of #JvdV was not exactly what I was after, a hat-tip to them for the idea of offsetting the whole column up and down, which led to this:
=LET(input,A4:A25,up,OFFSET(input,-1*(B1+1),0),down,OFFSET(input,B1,0),input*IF(IFERROR(up*down,0)>0,IF(up=down,1,0),1))
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})))
I need your help or a little advice with my problem. For example, have a table looking like this:
blahbla 4 5 7 44
lololol 8 7 8 45
kokooko 1 2 3 4
These table has 3 lines and 4 columns, but the number of lines and columns may vary. I need to read values from this table (it is no problem with fopen) but the problem is that i dont know how to access concrete values from this table. For example if I want to printf values only from first line, or only from third column, what am I supposed to do? give me please some advice without using malloc, thanks.
Find matrix size
At first you should find the matrix size. Rows will be easy, you only have to count number of lines (I'm assuming that you are reading data from .txt file). Next thing is columns. If all rows will have the same number of elements, you can iterate over the string that is the first line and check if elements of the string are letters (for example with isalpha function). If element is a letter, then you can increment the number of columns - if not, then it will be space or number, if it is a space then you should increment number of columns variable, and if it is not then you have to skip to the next element.
If the number of elements in rows of your table may vary, then you should iterate over every line and find the number of columns like in previous case, finding the maximum.
Create matrix and copy data
Now, when you have size of your matrix you can allocate it like this: string table[numberOfRows][numberOfColumns] - then you should once again iterate over the data in txt file, checking if the element in line is alpha or is space. If it is a space and the next character is numeric(you can check it with isdigit and isspace), then you should make some string variable that you will be concatenating until it hits another space or end of line - then you assign it to matrix. If it is letter then it will be easy, just assign it to proper place in the matrix. Remeber that you will have to fill additional elements in the matrix with something like "0" (of course only if the rows can have different number of elements).
Retrieve data
You can retrieve data only from column or a row, simply create an array that has size of your table columns or rows, then you can for example iterate over your table and check if the row(column) is the one that is interesting you. And if it is, assign it to your array. Then you can print it with another loop.
I was trying to think of an algorithm which chooses 6 random cells from an array with 50 cells, such that the probability for each cell to be picked is equal.
I need to find a solution that uses the function Random(start,end) no more than 6 times.
I can't use any extra data structure, and it is important that the probability for each cell to be picked will be equal and independent.
Call Random(0,49). Read the resulting cell, then shuffle everything after it in the array down one place so that you have a 49-cell array with the picked value missing.
Call Random(0,48) and repeat 6 times.
Put the cells in a list, shuffle it, take six of 'em