2
votes

I have a testfile.txt, which is a 4 x 4 matrix and tab delimited

1    1    3    4
2    2    3    4
3    1    3    4
4    2    3    4

The output i want is like so:

  1. If it detects that the second column has a 1, insert a new column on the right side, and the new column should contains something like x=[1 1 0 3]

  2. If it detects that the second column has a 2, insert a new column on the right side, and the new column should contains something like y=[2 3 4 5]

This is how the output should look like:

1    1    x=[1    1    0    3]    3    4
2    2    y=[2    3    4    5]    3    4
3    1    x=[1    1    0    3]    3    4
4    2    y=[2    3    4    5]    3    4

Ultimately, in MATLAB this is the output I want to get:

1    1    1    1    0    3    3    4
2    2    2    3    4    5    3    4
3    1    1    1    0    3    3    4
4    2    2    3    4    5    3    4

What I've tried is:

test=dlmread('testfile.txt','\t');
m=length(test);
for i=1:m
    if find(test(:,2)==1)>0
        x=[1    1   0   3];
        test=[test(:,1) x test(:,3:4)];
    elseif find(test(:,2)==2)>0
        y=[2    3    4    5];
        test=[test(:,1) y test(:,3:4)];   
    dlmwrite('testfile.txt',test,'delimiter','\t','precision','%.4f');
    end
end

The error I get is the following:

Dimensions of matrices being concatenated are not consistent.

The error is from the following statement:

Error in : test=[test(:,1) x test(:,3:4)]

I'll be really appreciative if someone can help me, since i'm quite new in MATLAB.

Thanks in advance!

1
What if second column is [1; 2; 3; 1]? Can that happen?Luis Mendo

1 Answers

2
votes

Here is a completely vectorized solution for you. Let's go through this one step at a time. You obviously are reading in the text data right, so let's keep that code the same.

test = dlmread('testfile.txt','\t');

What I'm going to do is create a 2D array where the first row corresponds to your x that you want to insert, while the second row corresponds to the y that you want to insert. In other words, create a variable called insertData such that:

insertData = [1 1 0 3; 2 3 4 5];

Next, you simply have to use the second column to figure out which row of data from insertData you want to insert into your final matrix. You can then use this to create your final matrix, which we will store in testOut. In other words:

testOut = [test(:,1:2) insertData(test(:,2),:) test(:,3:4)]

The output I get is:

testOut =

 1     1     1     1     0     3     3     4
 2     2     2     3     4     5     3     4
 3     1     1     1     0     3     3     4
 4     2     2     3     4     5     3     4

Let's walk through the above code slowly. The first two columns of your data stored in test and the last two columns in your data stored in test are the same. You want to insert the data right in the middle. As such, you create a new matrix called testOut where the first two columns are the same, and then in the middle is where it gets interesting. Every time the second column has a 1, we access the first row of insertData, and we place our data in the corresponding row. Every time the second column has a 2, we access the second row of insertData, and we place our data in the corresponding row. To finish everything off, the last two columns should be the same.


Minor Note

If you want to understand why your code isn't working, it's because you are not concatenating the rows properly. In addition, in your for loop, you are using : to access all of the rows for a particular column when you should be accessing one row at a time... at least that's how I'm interpreting your for loop. This change must also be done in your if statements. Also, you are adding onto the test variable, when you need to declare a NEW variable. Also, you need to move the dlmwrite method so that it is called AFTER the for loop has finished and you have finished creating the new matrix. The combination of all of these things is ultimately why you are getting errors in your code.

Basically, what you need to do, if you want to use your code, is do this:

test=dlmread('testfile.txt','\t');
m=length(test);
testOut = []; %// Must declare NEW variable
for i=1:m
    if find(test(i,2)==1)>0 %// Change
        x=[1    1   0   3];
        testOut=[testOut; test(i,1) x test(i,3:4)]; %// NEW
    elseif find(test(i,2)==2)>0 %// Change
        y=[2    3    4    5];
        testOut=[testOut; test(i,1) y test(i,3:4)];   %// NEW
    end
end

%// Move this out!
dlmwrite('testfile.txt',testOut,'delimiter','\t','precision','%.4f');

Take a look at how testOut is being concatenated in the for loop. You are going to take the current state of testOut, move to the next row using ; then add your new data in.

This code should now work, but you can easily achieve what you want to do in just two lines.


Hope this helped!