MATLAB Answers

0

How do I create 2 separate matrices which are pair-matched to each other in the corresponding row from 2 original CSV files?

Asked by Yen Yi Tan on 28 Aug 2019
Latest activity Commented on by Bob Nbob
on 30 Aug 2019
I currently have two datasets of samples in two separate CSV files which I want to run a pair-matched network medical analysis on. Each of these have the same medical variables per dataset but have different sample numbers. For example, my first dataset contains 22 samples of ill patients with 18 medical variables. My second dataset contains 109 samples of recovered patients with 18 medical identical variables.
I want to be able to pair-match these samples yet keep them intact in their individual datasets so I can run individual network graph analyses on them. So, ideally my end result would be: my first dataset would contain 22 samples (ill), and my second dataset would contain 22 samples (recovered). The sample in row A of dataset 1 and dataset 2 would be matched by a variable (e.g. variable X are the same), the sample in row B of dataset 1 and dataset 2 would be matched as well by that same variable and so on.
I’ve written out the logic of code, but I’m having trouble arriving at the actual code (novice issues):
  • Import ill dataset (22 samples) as a matrix of 22x18, name dataset “A”.
  • Import recovered dataset (109 samples) as a matrix of 109x18, name dataset “B”.
  • The variable to be pair matched is column 6.
  • Select ID1 (row 1 - let’s assume each row is identified by an individual identifier tag for this logical argument) of A and compare column 6 variable against ID1-ID109 column 6 variable of B.
  • If A-ID1-6 = B-IDX-6 with only a single return (where IDX is the row returned with the matching column 6 variable), then replace A-ID1 in row 1 of C (new NaN 22 matrix for pair-matched ill) and replace B-IDX in row 1 of D (new NaN 22 matrix for pair-matched recovered), removing B-IDX from the original matrix.
  • If A-ID1-6 = B-IDX-6 with multiple returns, then replace A-ID1 in row 1 of C and randomly select one of the returns in B-IDX and replace in row 1 of D, removing B-IDX from the original matrix.
  • If A-ID1-6 = B-IDX-6 with no returns, then select closest B-IDX-6 within +/-0.5 of the column 6 variable, replacing A-ID1-6 in row 1 of C and replacing B-IDX in row 1 of D, removing B-IDX from the original matrix. If there is no +/-0.5 match for variable in column 6, return both with a NaN in C and D and remove both from original matrices.
  • Loop for A-ID2 to A-ID22 until C and D have 22 rows each which are pair-matched.
  • These new data tables will then be individually used to generate network maps.
I do apologize for the lengthy explanation. It is frustrating as I can see the logic but can’t outright turn it into code that works. Please don’t hesitate to ask if there is lack of clarity in any area and thank you in advance for anyone who can help me out.

  4 Comments

Show 1 older comment
Hi Bob, thanks for the reply. So with regards to the simpler code I’m alright with it, e.g. A=importdata(‘illsample.csv’), creating the NaN matrices, doing simple if arguments and simple loop arguments. Those are not an issue for me when it’s a simpler logical argument, but beyond that I’m having a bit of trouble, so I don’t currently have any code to show for it.
I can do simple arguments like:
if true
% for i = 1:22,
if A(i,6)= B(i,6)
A(i,:)=C(i,:)
B(i,:)=D(i,:)
Else C(i,:) = C(i,:)
End
end
And then remove the selection from the original matrix. It starts to get me when there are multiple outcomes for an if argument, with all the criteria and deletions.
For multiple returns, it would be key that the selection should be random. Ideally I’m trying to create a system that will select at random instead of just selecting the first match or the first closest match to prevent bias.
However, any progress is progress and if it takes getting just the first match working initially, I’m all for it.
Why I’m removing the sample from A and B after running it is to prevent duplicate samples. For example if I pair-match a patient from B to another patient in A, I don’t want the patient in B to be appearing twice in D, which would skew my results in the network graph.
However, that being said, it’s not necessarily a removal of the sample that has already been run. If there’s any other way to exclude it that would also solve the issue.

Sign in to comment.

Products


Release

R2018b

1 Answer

Answer by Bob Nbob
on 28 Aug 2019
 Accepted Answer

This is a first cut at how I would set up the loop and arguments.
for i = 1:size(A,1)
tmp = B(B(:,6)==A(i,6),:);
C(i,:) = A(i,:);
if isempty(tmp) % No matches
tmp = B(B(:,6)<=A(i,6)+0.5 & B(:,6)>=A(i,6)-0.5,:); % Expand range of check
end
if size(tmp,1)==1 & ~isempty(tmp)
D(i,:) = tmp;
elseif size(tmp,1)>1
r = randi([1:size(tmp,1)]);
D(i,:) = tmp(r,:);
end
end
If you run your check, return no results, and don't get any results after the relaxed conditions you should end up with a row of NaNs.
I have not tested this, so there may be some slight errors. Feel free to debug as necessary.

  6 Comments

  1. i = 5 because that is the iteration where the error crashed the code. If you place a debug marker somewhere within the code and run it until it stops at the debug marker each time through the loop it will return a progressively higher integer. The for loop doesn't define i as the range of values from 1:x, but rather as a specific value within that range for each iteration of the loop.
  2. For A(5,6) there are five rows of B which return the same values, hence why tmp is 5x15. During the next iteration it would likely be a different size, perhaps 1x15, or [ ].
  3. Yes, per the error you need to change the range I defined to just min and max. The current min and max values are fine, you just need to set them as two parts to a matrix.
r = randi([1,size(tmp,1)]); % Just replace : with ,
Glancing things over, I suspect D is only 1x15 because A(2:4,6) found no matches, even with the expanded range check. Because of this and the second condition check, then there is no value actually printed to D. The row would be NaN if the matrix had been preinitialized, but it doesn't look like you did that, so there are no results printed. I would suggest preinitiallizing both C and D.
Hi Bob,
  1. Ah, so the i here is picking at the specific value of column 6 with every iteration that passes.
  2. Got it, I fully understand why and how having a temporary variable that resets with each loop works.
  3. Ah, they were a range to begin with with 1:size(tmp,1) but it was just the syntax in this case that was slightly incorrect for the randi input.
I've re-run the code and preinitialized C and D as you suggested. It didn't occur to me that the NaN matrix should be the default as the logic replaces a no return with whatever is in tmp, which isn't NaN by default.
You have been such an amazing help with my issue. Thank you for beng so patient with me. If I may ask, are there any specific resources you can recommend at getting better at MATLAB? I'm using it in a project focused manner, e.g. only using tools and syntax as required, but I can imagine it helps a fair bit to have some basic foundation. I still do struggle with syntax and understanding how to make the code flow, even if I can see the logic clearly.
The two things that have helped me be better at MATLAB, besides projects, are being active on these forums, and 'Cody' here on the mathworks website. The first has introduced me to a number of new concepts, or better ways of doing what I already know, while the second has offered me a wide variety of small challenges that I can learn how to solve without having to jump into some major project.
Other than that, reading the documentation, coupled with the forums, has helped teach me the vocabulary that the Matlab world tends to use, which makes it much easier to look at the documentation for new functions and be able to pick them up quickly.

Sign in to comment.