Changing the value of elements in a table, depending on a specific string for MATLAB - matlab

Suppose I have a MATLAB table of the following type:
Node_Number Generation_Type Total_power(MW)
1 Wind 600
1 Solar 452
1 Tidal 123
2 Wind 200
2 Tidal 159
What I want to do is to produce a table with exactly same dimensions, with the only difference being the value of the data of the Total_Power column that corresponds to the Wind generation type being multiplied with 0.5. Hence the result that I would get would be:
Node_Number Generation_Type Total_power(MW)
1 Wind 300
1 Solar 452
1 Tidal 123
2 Wind 100
2 Tidal 159
What I believe that would do the trick is some code which would scan all the rows that have the string 'Wind', and then after locating the rows which have this string, to multiply the 3rd column of this row with 0.5. A for loop seems like a viable solution, though I am not sure how to implement this. Any help would be greatly appreciated.

Just find the index of rows with the category Wind, and then you could have access to them by calling T(index,:).
clc; clear;
T=readtable('data.txt');
rows = find(ismember(T.Generation_Type,'Wind'));
T(rows,:).Total_power_MW_=T(rows,:).Total_power_MW_*0.5
Output:
Node_Number Generation_Type Total_power_MW_
___________ _______________ _______________
1 'Wind' 300
1 'Solar' 452
1 'Tidal' 123
2 'Wind' 100
2 'Tidal' 159

Related

Calculating the weighted moving average of 2 lists using a set window

If I have two lists:
a:1 2 3 4;
b:10 20 30 40;
I want to sum the product of the two lists within a window of 2. So the result set should be:
10 50 130 250
For example, to get the result of 130 it would be (2*20)+(3*30) = 130
sums 2 mavg '(a*b)
seems to get me part way there, but the window of 2 isn't being applied. I've tried experimenting with sum, sums, sum each, wavg, mavg, etc. and I am completely stuck. Could anyone help? Thanks!
This line should work for you:
2 msum a*b
as demonstrated here:
q)a:1 2 3 4
q)b:10 20 30 40
q)2 msum a*b
10 50 130 250
For more information about the keyword msum, you could check out the Kx Reference page:
https://code.kx.com/wiki/Reference/msum
Hope that helps!
Alternatively you could use the adverb each prior:
q)+':[a*b]
However this will only work with a window size of 2 and if your data contains null values this needs to be padded with 0:
q)+':[0^a*b2]
On a positive note it is faster than using msum in this situation.
q)\ts:1000000 +':[0^a*b2]
940 1264
q)\ts:1000000 2 msum a*b2
1556 1104

How to sort parts of table in Matlab?

I have a table in Matlab containing test data from different test persons. The test has seven video clips each with four different audio versions, which the test persons must rate on a scale from 1 to 100. Every video clip is presented twice for statistical accuracy. The test person pushes buttons 1-4 on an interface to hear the different audio versions.
My table contains the following columns (among some others that are not relevant for the question):
Test Person ID Audio Version Video Clip Rating
1 1 Forest 40
1 2 Forest 60
1 3 Forest 20
1 4 Forest 100
Now, to introduce minimal bias towards any favor of a particular button during the test, the audio versions are randomly permuted between every video clip. This means the real data will look somewhat more like this (Audio Version not sorted):
Test Person ID Audio Version Video Clip Rating
1 1 Forest 40
1 2 Forest 60
1 3 Forest 20
1 4 Forest 100
1 3 City 10
1 2 City 50
1 1 City 40
1 4 City 7
1 4 Inside 90
1 2 Inside 58
1 1 Inside 22
1 3 Inside 35
What I want to do is to: Maintain the correct order of the video clips, thus still have Forest -> City -> Inside, but have them all ordered so that is always audio version 1, 2, 3, 4:
Test Person ID Audio Version Video Clip Rating
1 1 Forest 40
1 2 Forest 60
1 3 Forest 20
1 4 Forest 100
1 1 City 40
1 2 City 50
1 3 City 10
1 4 City 7
1 1 Inside 22
1 2 Inside 58
1 3 Inside 35
1 4 Inside 90
My initial thought was to use the sortrow() function in Matlab and then sort them ascendingly along with the video clip, but since the video clips are introduced twice at different stages of the test and I want to maintain the same sequence of the clips in the table this doesn’t work. Also the same video clips are presented to numerous different test persons.
I am using a pre-made function that has to have the data sorted in this way to perform statistical calculations on it. This function takes the Matlab data from a struct and puts it into the table via a for-loop row for row.
Because the data is put into the table via a for-loop I thought there might be a way to only sort a fixed number of rows at a time i.e row 1-4, 5-8, 9-12 and so on. Do you know if there is a way to sort only part of a table in Matlab?
You can do this with a single call to sortrows by creating an additional numeric column representing your fixed pattern of video presentations. This additional column will simply label each set of 4 rows with a successive integer. It can be concatenated to the beginning of the table, then you can sort by the first and third columns to get the ordering you want:
[~, index] = sortrows([table(ceil((1:size(T, 1)).'./4)) T], [1 3]);
T = T(index, :);
And the output:
T =
ID Audio Video Rating
__ _____ ________ ______
1 1 'Forest' 40
1 2 'Forest' 60
1 3 'Forest' 20
1 4 'Forest' 100
1 1 'City' 40
1 2 'City' 50
1 3 'City' 10
1 4 'City' 7
1 1 'Inside' 22
1 2 'Inside' 58
1 3 'Inside' 35
1 4 'Inside' 90
Using reshape and sort you can do:
[~,idx]=sort(reshape(Audio_Version,4,[]));
idxtble = bsxfun(#plus,idx,0:4:(4*size(idx,2))-1);
table2 = table1(idxtble,:);
Explanation:
You can extract the audio column and reshape it to to [4 * n] matrix:
audio = reshape(Audio_Version,4,[]);
then sort columns of audio and get indexes of sorted elements:
[~,idx]=sort(audio);
Here idx represents row numbers of the sorted elements.
Convert idx to linear indexes of the whole column of the table:
idxtbl = bsxfun(#plus,idx,0:4:(4*size(idx,2))-1);
Reorder the table:
table2 = table1(idxtbl,:);
Just using sortrow for the specified part of the table like the following:
table(1:4,:) = sortrow(table(1:4,:), 2);
table(4:8,:) = sortrow(table(4:8,:), 2);
table(8:12,:) = sortrow(table(8:12,:), 2);
First sort the part of the table, then replace it with that part.

How to insert a value

I want to insert a number in the following matrix: n x 1 matrix
6
103
104
660
579
750
300
299
300
750
579
661
580
760
302
301
302
760
580
662
581
How to I insert it in the middle and shift the remaining numbers? I tried the following code:
Idx=[723];
c=false(1,length(Element_set2)+length(Idx));
c(Idx)=true;
result=nan(size(c));
result(~c)=Element_set2;
result(c)=8
You are complicating things. Simply find the middle index by finding the length of the array, dividing by 2 and truncating any decimal points, then using simply indexing to update the new matrix. Supposing that result is the column vector that was created by you and number is the value you want to insert in the middle, do the following:
number = 8; %// Change to suit whatever number you desire
middle = floor(numel(result) / 2);
result = [result(1:middle); number; result(middle+1:end)];
In the future, please read this great MATLAB tutorial on indexing directly from MathWorks: http://www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html. It's a good resource on the kinds of indexing operations one expects from starting out in MATLAB.

Matlab simulation: Query regarding generating random numbers

I am doing some simulations studies and for initial stuides I am trying to simulate 100 gas particles and then grouping of these gas particles in 5 groups randomly for 10 or 100 times (non zero values in any groups). after that i have to find the group with highest particle and the number.
for example
100 gas particles
1 2 3 4 5(groups) Total particle group/Highest number
20|20|20|20|20 100 1-2-3-4-5/20
70|16|04|01|09 100 1/70
18|28|29|10|15 100 3/29
.
.
etc
i have used this to generate 5 random numbers for a single time
for i=1:1
randi([1,100],1,5)
end
ans =
50 41 9 60 88
but how will i find the highest number and group?
Use the max function :
a = [50 41 9 60 88];
[C,I] = max(a)
C should be equal to 88 and I to 4.
For the special case of equality (first line in your code), you have to read the documentation to see the result of max. I think the index returned will be the first max.

sorting a timer in matlab

ok it seems like a simple problem, but i am having problem
I have a timer for each data set which resets improperly and as a result my timing gets mixed.
Any ideas to correct it? without losing any data.
Example
timer col ideally should be
timer , mine reads
1 3
2 4
3 5
4 6
5 1
6 2
how do i change the colum 2 or make a new colum which reads like colum 1 without changing the order of ther rows which have data
this is just a example as my file lengths are 86000 long , also i have missing timers which i do not want to miss , this imples no data for that period of time.
thanks
EDIT: I do not want to change the other columns. The coulm 1 is the gps counter and so it does not sync with the comp timer due to some other issues. I just want to change the row one such that it goes from high to low without effecting other rows. also take care of missing pts ( if i did not care for missing pts simple n=1: max would work.
missing data in this case is indicated by missing timer. for example i have 4,5,8,9 with missing 6,7
Ok let me try to edit agian
its a 8600x 80 matrix of data:
timer is one row which should go from 0 to 8600
but timer starts at odd times , so i have start of data from middle , lets say 3400, so in the middle of day my timer goes to 0 and then back to 1.
but my other rows are fine. I just need 2 plot other sets based on timer as time.
i cannot use T= 1:length(file) as then it ignores missed time stamps ( timers )
for example my data reads like
timer , mine reads
1 3
2 4
3 5
4 8
5 9
8 1
9 2
so u can see time stamps 6,7 are missing.
if i used n=1:length(file)
i would have got
1 2 3 4 5 6 7
which is wrong
i want
1 2 3 4 5 8 9
without changing the order of other rows , so i cannot use sort for the whole file.
I assume the following problem
data says
3 100
4 101
5 102
NaN 0
1 104
2 105
You want
1 100
2 101
3 102
NaN 0
4 104
5 105
I'd solve the problem like this:
%# create test data
data = [3 100
4 101
5 102
NaN 0
1 104
2 105];
%# find good rows (if missing data are indicated by zeros, use
%# goodRows = data(:,1) > 0;
goodRows = isfinite(data(:,1));
%# count good rows
nGoodRows = sum(goodRows);
%# replace the first column with sequential numbers, but only in good rows
data(goodRows,1) = 1:nGoodRows;
data =
1 100
2 101
3 102
NaN 0
4 104
5 105
EDIT 1
Maybe I understand your question this time
data says
4 101
5 102
1 104
2 105
You want
1 4 101
2 5 102
4 1 104
5 2 105
This can be achieved the following way
%# test data
data = [4 101
5 102
1 104
2 105];
%# use sort to get the correct order of the numbers and add it to the left of data
out = [sort(data(:,1)),data]
out =
1 4 101
2 5 102
4 1 104
5 2 105
EDIT 2
Note that out is the result from the solution in EDIT 1
It seems you want to plot the data so that there is no entry for missing values. One way to do this is to make a plot with dots - there won't be a dot for missing data.
plot(out(:,1),out(:,3),'.')
If you want to plot a line that is interrupted, you have to insert NaNs into out
%# create outNaN, that has NaN-rows for missing entries
outNaN = NaN(max(out(:,1)),size(out,2));
outNaN(out(:,1),:) = out;
%# plot
plot(out(:,1),out(:,3))