MATLAB:将列中的值拆分为1或2个附加列

时间:2013-04-17 11:37:55

标签: matlab split

我有一个312x2矩阵,代表个别科目回答的问题数目(第2栏)(第1栏) e.g。

x =

    40    56
    41    56
    42   176
    43   176
    44   116
    45    56
    46    56
    47   116
    48    56
    49    56
    50   116

有些参与者不止一次回答问卷,我想将他们的数据分成额外的栏目。

即。参与者43完成了3次 - 一次56个问题,两次60个问题。

因此,我想将他们的数据分成3列,最后得到:

x = 
    40    56
    41    56
    42    56    60    60
    43    56    60    60
    44    56    60
    ...etc

然后我会用NaN填补空白,这样我就可以找出每份调查问卷所回答的平均问题。

4 个答案:

答案 0 :(得分:2)

这不是最优雅的解决方案,但它可以相对简单地完成工作:

x = [40 56;41 56;42 176;43 176;44 116;45 56;46 56;47 116;48 56;49 56;50 116];
a=x(:,2);
newData=[];
for i=1:size(a,1)
    if a(i)==56
        newData=vertcat(newData,[56 NaN NaN]);
    elseif a(i)==116
        newData=vertcat(newData,[56 60 NaN]);
    elseif a(i)==176
        newData=vertcat(newData,[56 60 60]);
    end
end
Data = horzcat(x(:,1),newData)

命令窗口:

Data =

40    56   NaN   NaN
41    56   NaN   NaN
42    56    60    60
43    56    60    60
44    56    60   NaN
45    56   NaN   NaN
46    56   NaN   NaN
47    56    60   NaN
48    56   NaN   NaN
49    56   NaN   NaN
50    56    60   NaN

答案 1 :(得分:1)

最好使用cell arrays来存储最终输出,因为每行可能包含不同数量的元素。

这是一个简短的解决方案,可以为您提供所需的结果:

C = mat2cell(x, ones(1, size(x, 1)), 2);
C(ismember(x(:, 1), cellfun(@(z)z(1), y))) = y;

其中x是问题中描述的原始数据数组,而y是一个包含新行(正如您所称, split )的单元格数组替换x

实施例

这是一个类似于问题中给出的简短示例:

%// Generate sample data
x = [40 56; 41 56; 42 176; 43 176; 44 116; 45 56];
y = {[43 56 60 60]; [44 56 60]};

%// Replace rows in x with matching rows in y
C = mat2cell(x, ones(1, size(x, 1)), 2);
C(ismember(x(:, 1), cellfun(@(z)z(1), y))) = y;

结果是一个新的单元格数组:

C =
    [40    56]
    [41    56]
    [42   176]
    [43    56    60    60]
    [44    56    60]
    [45    56]

要计算每个问卷回答的平均问题,请使用cellfun迭代单元格:

m = cellfun(@(x)mean(x(2:end)), C)

这个例子产生:

m =
   56.0000
   56.0000
  176.0000
   58.6667
   58.0000
   56.0000

答案 2 :(得分:0)

以下将实现您的需求:

B = unique(A(:,1));
m = max(hist(A(:,1),B));
B = [B, nan(numel(B),m)];
for ii=1:size(B,1)
    jj = (A==B(ii,1));
    B(ii,2:end) = [A(jj(:,1),2)', nan(1,m-sum(sum(jj(:,1))))];
end

输入:

A =

    53    83
    84    76
    52    99
    53    83
    76    90
    54    73
    91    72
    91    92
    86    54
    57    56

结果将是:

B =

    52    99   NaN
    53    83    83
    54    73   NaN
    57    56   NaN
    76    90   NaN
    84    76   NaN
    86    54   NaN
    91    72    92

答案 3 :(得分:0)

当您指定超出当前矩阵范围的内容时,MATLAB会自动为您扩展矩阵:

>> a = [
    40    56
    41    56
    42   176
    43   176
    44   116
    45    56
    46    56
    47   116
    48    56
    49    56
    50   116];     
>> a(3,3) = 60
a =
    40    56     0
    41    56     0
    42   176    60
    43   176     0
    44   116     0
    45    56     0
    46    56     0
    47   116     0
    48    56     0
    49    56     0
    50   116     0

默认操作是使用零填充(而不是NaN s)。如果您可以合理地期望永远不会成为任何回答0个问题的参与者,那么您可以做到

>> a(a==0) = NaN;
>> M = nanmean(a(:,2:end),2);

获得平均值。

如果您不能指望这一点(或者您没有/想要依赖统计工具箱来使用nanmean)那么您可以编写一些小函数来执行您想要的操作:

function new_a = addQsAnswered(old_a, QsAnswered)

    new_a = old_a;

    for ii = 1:size(QsAnswered,1)

        inds = (new_a(:,1) == QsAnswered(ii,1));

        if sum(isnan(new_a(inds,:))) < size(QsAnswered(:,2:end),2)
            new_a = [new_a NaN(size(new_a,1),1)]; %#ok            
        end

        new_a(inds,isnan(new_a(inds,:))) = QsAnswered(ii,2:end);        

    end

end

function M = getParticipantMeans(a)   
    M = zeros(size(a,1),1);    
    for ii = 1:size(a,1)
        as = a(ii,2:end);
        as = as(~isnan(as));
        M(ii) = sum(as)/numel(as);
    end    
end

示例:

>> addQsAnswered(a, [46 78 90; 49 60 78])
ans =
        40    56   NaN   NaN
        41    56   NaN   NaN
        42   176    60   NaN
        43   176   NaN   NaN
        44   116   NaN   NaN
        45    56   NaN   NaN
        46    56    78    90
        47   116   NaN   NaN
        48    56   NaN   NaN
        49    56    60    78
        50   116   NaN   NaN

>> getParticipantMeans(new_a)
ans =
        5.600000000000000e+001
        5.600000000000000e+001
        1.180000000000000e+002
        1.760000000000000e+002
        1.160000000000000e+002
        5.600000000000000e+001
        7.466666666666667e+001
        1.160000000000000e+002
        5.600000000000000e+001
        6.466666666666667e+001
        1.160000000000000e+002