2013-07-12 29 views
3

我有不同的列數的兩個數據集:如果不是所有變量都相同,如何連接兩個數據集?

DS1:

A B C 
1 2 3 

DS2:

A C D 
2 3 4 

現在,我想這兩個數據集合並:

結果:

A B C D 
1 2 3 0 
2 3 0 4 

正如你所看到的,如果兩個數據集中都不存在變量名,我只想添加0,NaN或空白。我試圖使用catjoin,但我無法弄清楚如何去做。任何提示?

+0

可以告訴你如何聲明這些數據集?他們是單元陣列嗎? – Floris

+0

@弗洛伊斯我從一個文件加載它們 – RoflcoptrException

回答

1

首先,我們創建的例子:

% Create test datasets: 
A=1; 
B=2; 
C=3; 
save db1 
A=2; 
clear B; 
D=4; 
save db2 
clear; 

現在腳本看起來或多或少是:

% Your script starts here, replace your paths with the correct paths: 
path_to_db1 = 'db1'; 
path_to_db2 = 'db2'; 

db1 = load(path_to_db1); 
db2 = load(path_to_db2); 

merge = db1; 

for field = fieldnames(db1)' 
    field = field{1}; 
    if isfield(db2,field) 
    merge.(field) = [merge.(field);db2.(field)]; 
    else 
    merge.(field) = [merge.(field);0]; 
    end 
end 

for field = fieldnames(db2)' 
    field = field{1}; 
    if ~isfield(db1,field) 
    merge.(field) = [0;db2.(field)]; 
    end 
end 
clear db1 db2; 

輸出:

>> merge.A 

ans = 

    1 
    2 

>> merge.B 

ans = 

    2 
    0 

>> merge.C 

ans = 

    3 
    3 

>> merge.D 

ans = 

    0 
    4 

但是你可能他們想是工作區上的自由變量,而不是合併結構,因此您可以添加以下代碼:

for field = fieldnames(merge)' 
    field=field{1}; 
    eval(sprintf('%s = merge.%s;',field,field)); 
end 
3

這是一個醜陋的方式來做到這一點 - 然後一個更清晰的方式(稍後添加)。問題是,只要你使用單元陣列(因爲數據類型是混合的 - 字母表中的字母,然後數字),生活變得很難。通過創建一個結構,其中列名和數據是兩個單獨的數組(參見下文),您可以做得更好......但現在這裏是「解決方案」。通過在兩個數據集中有不同數量的行以及不同數量的列,我讓生活更有趣 - 只是爲了確保不會破壞某些東西。

ds1 = {'a','bb','c';1,2,3}; 
ds2 = {'aa','c','d', 'e';2,3,4,5; 5,6,7,8}; 
cols = unique({ds1{1,:} ds2{1,:}}); 

ds3 = cols; 
n1 = size(ds1,1) - 1; 
%% 
for ii = 1:size(ds1,2) 
    ci = find(cellfun(@(x) isequal(x, ds1{1,ii}), cols)); 
    if numel(ci) > 0 
     for jj = 1:n1 
      ds3{1+jj,ci} = ds1{1+jj, ii}; 
     end 
    end 
end 
n2 = size(ds2, 1) - 1; 
for ii = 1:size(ds2,2) 
    ci = find(cellfun(@(x) isequal(x, ds2{1,ii}), cols)); 
    if numel(ci) > 0 
     for jj = 1:n2 
      ds3{1+n1+jj,ci} = ds2{1+jj, ii}; 
     end 
    end 
end 

生成的合併數組:

'a' 'aa' 'bb' 'c' 'd' 'e' 
[1]  [] [ 2] [3] [] [] 
[] [ 2]  [] [3] [4] [5] 
[] [ 5]  [] [6] [7] [8] 

不是最優的,我敢肯定 - 但它確實你問什麼......我討厭在循環中這樣做,但不能看到周圍的方式它。我希望其中一位「真正的Matlab專家」會在他看到這個時候嘔吐,並被激勵成爲您提供一個明智的答案。

編輯我想過這個多一些,並用更高效的算法上來:

% assuming column headers and data are in two separate arrays 
ds1headers = {'a','bb','c'}; 
ds1data = [1 2 3; 2 3 4]; 
ds2headers = {'aa','c','d', 'e'}; 
ds2data = [2 3 4 5; 3 4 5 6; 4 5 6 7]; 

% as before, find unique column headers: 
cols = unique({ds1headers{:} ds2headers{:}}); 

% convert to column numbers: 
ds1conv = cellfun(@(x)find(ismember(cols, x)), ds1headers); 
ds2conv = cellfun(@(x)find(ismember(cols, x)), ds2headers); 

% now conversion is easy: 
n1 = size(ds1data,1); 
n2 = size(ds2data,1); 
ds3data = zeros(n1+n2, numel(cols)); 

ds3data(1:n1, ds1conv) = ds1data; 
ds3data(n1+(1:n2), ds2conv) = ds2data; 

disp(cols) 
disp(ds3data) 

結果是

'a' 'aa' 'bb' 'c' 'd' 'e' 

1  0  2  3  0  0 
2  0  3  4  0  0 
0  2  0  3  4  5 
0  3  0  4  5  6 
0  4  0  5  6  7 

看起來像它會做的伎倆 - 和沒有醜陋的循環......我現在認識到,這看起來有點像@ Magla的解決方案下面(當我發佈我的更新時沒有看到它,但顯然是在我最近編輯之前) - 除了我還有一個單元陣列列名和其他一些我mprovements。

+0

請參閱我所做的有關單元格的編輯。這是_ismember_與矩陣和單元格一起工作的魔力。 @RoflcoptrException,請您接受一個答案或給出您期望的答案更詳細的描述,以提供後續跟進嗎?非常感謝! (有一個人試圖在這裏建立聲望;) – marsei

+0

@Magla - 感謝您的跟進。你是對的 - 'ismember'是我工具箱中一個相對較新的東西,我仍然在學習它是多麼有用。 – Floris

3

我會去這樣的事情。它用零填充最終的矩陣。

%examples (ABCD are replaced by indexes 1234) 
A = [1 2 3; 11 12 13]; 
B = [1 3 5 8; 111 112 113 114]; 

%first mix the first rows of A and B 
header = union(A(1,:), B(1,:)) 

%find the corresponding indexes in A and B 
[Lia,LocbA] = ismember(A(1,:),header); 
[Lia,LocbB] = ismember(B(1,:),header); 


%concatenate the second rows of A and B 
C = header 
C(2,LocbA) = A(2,:); 
C(3,LocbB) = B(2,:); 

結果:

A =

1  2  3 
11 12 13 

B =

1  3  5  8 
111 112 113 114 

C =

1  2  3  5  8 
11 12 13 0  0 
111 0  112 113 114 

編輯:最初提供的代碼也適用於單元格(請參閱下面的示例)。在這種情況下,它用空單元格填充最終的單元陣列。與@Floris解決方案相反,要合併的數據集由列標題(第一行)和數據(第二行)組成。我猜你的數據格式將適合這兩種解決方案之一。

%input modification (now with cells) 
A = {'A' 'B' 'C';  11 12 13}; 
B = {'A' 'C' 'E' 'H'; 111 112 113 114}; 

結果:

C =

'A'  'B'  'C'  'E'  'H' 
[ 11] [12] [ 13] []  [] 
[111] []  [112] [113] [114] 
相關問題