MATLAB: Write Dynamic matrix to Excel - excel

I'm using MATLAB R2009a and following this example:
http://uk.mathworks.com/help/matlab/matlab_external/using-a-matlab-application-as-an-automation-client.html
I'd like to edit it so that I can write a matrix of unknown size into a column in an excel sheet, therefore not explicitly stating the range. I've attempted it this way:
%Put MATLAB data into the worksheet
Hop = [47; 53; 93; 10]; %Pretend I don't know what size this matrix is.
p = length(Hop);
p = strcat('A',num2str(p));
eActivesheetRange = e.Activesheet.get('Range','A1:p');
eActivesheetRange.Value = Hop;
However, this errors out. I've tried several variations of this to no avail. For example, using 'A:B' puts this array in columns A and B in excel and a NAN into every cell beyond my array. As I only want column A filled, using simple ('Range','A') errors out also.
Thanks in advance for any advice you can offer.

You're having issues because you're trying to use your variable p in a string directly
range = 'A1:p';
'A1:p'
This isn't going to work, you want to include the value of p. There are a number of ways you can do this.
In the code you have provided, you have already set p = 'A10' so if you wanted to append that to your range, you'd perform string concatenation
p = 'A10';
range = strcat('A1:', p);
I personally prefer to use sprintf to place the number directly into my strings rather than concatenating a bunch of strings.
p = 10;
range = sprintf('A1:A%d', p)
'A1:A10`
So if we adapt your code to use this we should get
range = sprintf('A1:A%d', numel(Hop));
eActivesheetRange = e.Activesheet.get('Range', range);
eActivesheetRange.Value = Hop;
Also just to be a little explicit, I would use numel rather than length as length is ambiguous. Also, I would flatten Hop into a column vector just to make sure that it's the proper dimension to be written to the spreadsheet.
eActivesheetRange.Value = Hop(:);

Essentially, the idea is to replace xx in 'B1:Bxx' with the number of elements in your matrix.
I tried this:
e = actxserver('Excel.Application');
eWorkbook = e.Workbooks.Add;
e.Visible = 1;
eSheets = e.ActiveWorkbook.Sheets;
eSheet1 = eSheets.get('Item',1);
eSheet1.Activate;
A = [1 2 3 4];
eActivesheetRange = e.Activesheet.get('Range','A1:A4');
eActivesheetRange.Value = A;
The above is directly from the link you shared. The reason why what you are trying to do is failing is that the p you pass into e.Activesheet.get() is a variable and not a string. To avoid this, try the following:
B = randi([0 10],10,1)
eActivesheetRange = e.Activesheet.get('Range',['B1:B' num2str(numel(B))]);
eActivesheetRange.Value = B;
Here, num2str(numel(B)) will pass in a string, which is the number of elements in B. This is variable in the sense that it depends on the number of elements in B.

Related

How to create idendical variables in MATLAB from an array of variable names?

I have the following code in Matlab:
a = zeros(23,1)
b = zeros(23,1)
c = zeros(23,1)
How can I write it more compactly? I was looking for a solution that is something like this:
str = {'a','b','c'}
for i = str{i}
i = zeros(23,1)
end
But I can't find a way to do it properly without an error message. Can someone help please?
Here is a compact way using deal :
[a, b, c] = deal(zeros(23,1));
You can also use a struct if the variable name is important:
str = {'a','b','c'};
data = struct
for ii = 1:numel(str)
data.(str{ii}) = zeros(23,1);
end
The struct is more efficient than the table. You can now address data.a, data.b, etc.
But if the name is not useful, it's best to put your data into a cell array:
N = 3;
data = cell(N,1);
for ii = 1:N
data{ii} = zeros(23,1);
end
or simply:
data = cell(3,1);
[data{:}] = deal(zeros(23,1));
Now you address your arrays as data{1}, data{2}, etc., and they're always easy to address in loops.
What you're tempted to do is very bad practise, but can be done like this
str = {'a','b','c'};
for ii = 1:numel(str)
eval( [str{ii} ' = zeros(23,1)'] );
end
Why is this bad practise?
Your code legibility has just gone way down, you can't clearly see where variables are declared.
eval should be avoided
You could use deal to make things a bit nicer, but this doesn't use the array of variable names
[a, b, c] = deal( zeros(23, 1) );
Even better, it's likely you can optimise your code by using a matrix or table instead of separate 1D arrays. The table option means you can still use your variable name array, but you're not using eval for anything!
% Matrix
M = zeros( 23, 3 ); % Index each column as a/b/c using M(:,1) etc
% Table, index using T.a, T.b, T.c
T = array2table( zeros(23,3), 'VariableNames', {'a','b','c'} );

Splitting the output obtained by Counter in Python and pushing it to Excel

I am using the counter function to count every word of the description of 20000 products and see how many times this word repeats like 'pipette' repeats 1282 times.To do this i have split a column A into many columns P,Q,R,S,T,U & V
df["P"] = df["A"].str.split(n=10).str[0]
df["Q"] = df["A"].str.split(n=10).str[1]
df["R"] = df["A"].str.split(n=10).str[2]
df["S"] = df["A"].str.split(n=10).str[3]
df["T"] = df["A"].str.split(n=10).str[4]
df["U"] = df["A"].str.split(n=10).str[5]
df["V"] = df["A"].str.split(n=10).str[6]
This shows the splitted products
And the i am individually counting all of the columns and then add them to get the total number of words.
d = Counter(df['P'])
e = Counter(df['Q'])
f = Counter(df['R'])
g = Counter(df['S'])
h = Counter(df['T'])
i = Counter(df['U'])
j = Counter(df['V'])
m = d+e+f+g+h+i+j
print(m)
This is the image of the output i obtained on using counter.
Now i want to transfer the output into a excel sheet with the Keys in one column and the Values in another.
Am i using the right method to do so? If yes how shall i push them into different columns.
Note: Length of each key is different
Also i wanna make all the items of column 'A' into lower case so that the counter does not repeat the items. How shall I go about it ?
I've been learning python for just a couple of months but I'll give it a shot. I'm sure there are some better ways to perform that same action. Maybe we both can learn something from this question. Let me know how this turns out. GoodLuck
import pandas as pd
num = len(m.keys())
df = pd.DataFrame(columns=['Key', 'Value']
for i,j,k in zip(range(num), m.keys(), m.values()):
df.loc[i] = [j, k]
df.to_csv('Your_Project.csv')

Combination of one of every string group in all possible combinations and orders in matlab

So I forgot a string and know there is three substrings in there and I know a few possibilities for each string. So all I need to do is go through all possible combinations and orders until I find the one I forgot. But since humans can only hold four items in their working memory (definately an upper limit for me), I cant keep tabs on which ones I examined.
So say I have n sets of m strings, how do I get all strings that have a length of n substrings consisting of one string from each set in any order?
I saw an example of how to do it in a nested loop but then I have to specify the order. The example is for n = 3 with different m`s. Not sure how to make this more general:
first = {'Hoi','Hi','Hallo'};
second = {'Jij','You','Du'};
third = {'Daar','There','Da','LengthIsDifferent'};
for iF = 1:length(first)
for iS = 1:length(second)
for iT = 1:length(third)
[first{iF}, second{iS}, third{iT}]
end
end
end
About this question: it does not solve this problem because it presumes that the order of the sets to choose from is known.
This generates the cartesian product of the indices using ndgrid.
Then uses some cellfun-magic to get all the strings. Afterwards it just cycles through all the permutations and appends those.
first = {'Hoi','Hi','Hallo'};
second = {'Jij','You','Du'};
third = {'Daar','There','Da','LengthIsDifferent'};
Vs = {first, second, third};
%% Create cartesian product
Indices = cellfun(#(X) 1:numel(X), Vs, 'uni', 0);
[cartesianProductInd{1:numel(Vs)}] = ndgrid(Indices{:});
AllStringCombinations = cellfun(#(A,I) A(I(:)), Vs, cartesianProductInd,'uni',0);
AllStringCombinations = cat(1, AllStringCombinations{:}).';%.'
%% Permute what we got
AllStringCombinationsPermuted = [];
permutations = perms(1:numel(Vs));
for i = 1:size(permutations,1)
AllStringCombinationsPermuted = [AllStringCombinationsPermuted; ...
AllStringCombinations(:,permutations(i,:));];
end

MATLAB - storing string

I would like to create something to store string, for example:
for x = 1:3
fruit = strcat('orange', num2str(x));
A = {fruit};
how can I make an output of a 1x3 matrix of
A =
orange1
orange2
orange3
I have tried a few things but nothing worked.
I do not think it is complicated, but I just don't seem to get my head round it.
and after I completed this, would I be able to combine a normal numerical matrix with A such that:
N = [1 2; 3 4; 5 6];
FINAL = [N A];
>>output of FINAL would look like
FINAL =
1 2 orange1
3 4 orange2
5 6 orange3
In MatLab, numerical arrays can only be concatenated with numerical arrays. If you want to create an array with varying data types, you need to use Cell Arrays.
To answer your first question, I would advise you to first declare fruit as a cell array, and then fill it with the desired data :
fruit = cell(3,1);
for i =1:3
fruit{i} = strcat('orange',num2str(i));
end
fruit
This should produce the desired output.
For your second question, if you want to concatenate a numerical array with a cell array, you first need to convert it to a cell array using num2cell, such as :
N = [1 2;3 4;5 6];
FINAL = [num2cell(N),fruit]
In that case, FINAL will be an array of 9 cells, that you could access like FINAL{1,3} = orange1. To write compact code with cells, you should take a look at cellfun and deal which are two useful functions.
Hope this helps !
for x = 1:3
fruit = ['orange', num2str(x)];
A{x,1} = fruit;
end
N = [1 2; 3 4; 5 6];
N_as_cell = num2cell(N);
FINAL = cat(2, N_as_cell, A);

How to concat string + i?

for i=1:N
f(i) = 'f'+i;
end
gives an error in MatLab. What's the correct syntax to initialize an array with N strings of the pattern fi?
It seems like even this is not working:
for i=1:4
f(i) = 'f';
end
You can concatenate strings using strcat. If you plan on concatenating numbers as strings, you must first use num2str to convert the numbers to strings.
Also, strings can't be stored in a vector or matrix, so f must be defined as a cell array, and must be indexed using { and } (instead of normal round brackets).
f = cell(N, 1);
for i=1:N
f{i} = strcat('f', num2str(i));
end
For versions prior to R2014a...
One easy non-loop approach would be to use genvarname to create a cell array of strings:
>> N = 5;
>> f = genvarname(repmat({'f'}, 1, N), 'f')
f =
'f1' 'f2' 'f3' 'f4' 'f5'
For newer versions...
The function genvarname has been deprecated, so matlab.lang.makeUniqueStrings can be used instead in the following way to get the same output:
>> N = 5;
>> f = strrep(matlab.lang.makeUniqueStrings(repmat({'f'}, 1, N), 'f'), '_', '')
f =
1×5 cell array
'f1' 'f2' 'f3' 'f4' 'f5'
Let me add another solution:
>> N = 5;
>> f = cellstr(num2str((1:N)', 'f%d'))
f =
'f1'
'f2'
'f3'
'f4'
'f5'
If N is more than two digits long (>= 10), you will start getting extra spaces. Add a call to strtrim(f) to get rid of them.
As a bonus, there is an undocumented built-in function sprintfc which nicely returns a cell arrays of strings:
>> N = 10;
>> f = sprintfc('f%d', 1:N)
f =
'f1' 'f2' 'f3' 'f4' 'f5' 'f6' 'f7' 'f8' 'f9' 'f10'
Using sprintf was already proposed by ldueck in a comment, but I think this is worth being an answer:
f(i) = sprintf('f%d', i);
This is in my opinion the most readable solution and also gives some nice flexibility (i.e. when you want to round a float value, use something like %.2f).
according to this it looks like you have to set "N" before trying to use it and it looks like it needs to be an int not string? Don't know much bout MatLab but just what i gathered from that site..hope it helps :)
Try the following:
for i = 1:4
result = strcat('f',int2str(i));
end
If you use this for naming several files that your code generates, you are able to concatenate more parts to the name. For example, with the extension at the end and address at the beginning:
filename = strcat('c:\...\name',int2str(i),'.png');

Resources