Вернуть максимальное значение каждой подгруппы в таблице - PullRequest
2 голосов
/ 02 июня 2019

У меня есть такой раздел таблицы:

X     Y    Value
__   __    __   
1    2     6.9   
1    3     6.8   
1    4     8.1 
2    1     7.2 
2    3     11.7
2    4     16
3    1     22.6
3    2     20.5
3    3     18.1
… … …

Для каждой группы строк, имеющих одинаковый X, мне нужно выбрать только строку, имеющую наибольшее Value. Как я могу сгенерировать такую ​​таблицу?

X     Y    Value 
__   __    __   
1   4      8.1 
2   4      16
3   1      22.6

Код, который у меня есть, дает только одну строку:

X = [1; 1; 1; 2; 2; 2; 3; 3; 3];
Y = [2; 3; 4; 1; 3; 4; 1; 2; 4];
Value = [6.9; 6.8; 8.1;7.2;11.7;16;22.6;20.5;18.1];
T = table(X,Y,Value);
[~,maxidx] = max(Value);
T(maxidx,:)
%{
ans =
  1×3 table
    X    Y    Value
    _    _    _____
    3    1    22.6 
%}

Ответы [ 3 ]

3 голосов
/ 02 июня 2019

Если вы используете R2015b или новее, вы можете использовать splitapply:

function T2 = q56413455()
% Define some example inputs:
X = [1; 1; 1; 2; 2; 2; 3; 3; 3];
Y = [2; 3; 4; 1; 3; 4; 1; 2; 4];
Value = [6.9; 6.8; 8.1;7.2;11.7;16;22.6;20.5;18.1];
T = table(X,Y,Value);
% Call the "business logic" and assign the output:
T2 = getMaxRows(T);

function out = getMaxRows(T)
GROUPING_VAR = 1; % We assume that the 1st column contains the grouping variable
varnames = T.Properties.VariableNames;
tmp = splitapply(@maxrow, T, T.(varnames{ GROUPING_VAR }));
out = array2table(tmp, 'VariableNames', varnames );

function outrow = maxrow(varargin)
COL_WITH_MAX = 3; % We assume that the 3rd columns is the one that matters for max()
subArr = cell2mat(varargin);
[~,I] = max(subArr(:,COL_WITH_MAX));
outrow = subArr(I,:);

Вызов этого дает желаемый результат:

>> q56413455
ans =
  3×3 table
    X    Y    Value
    _    _    _____
    1    4     8.1 
    2    4      16 
    3    1    22.6 

В другом варианте используется вывод 2 nd , равный splitapply(@max, ...), который является индексом максимума в группе. Затем нам нужно добавить к этому количество элементов в предыдущих группах (это делается с помощью diff):

X = [1; 1; 1; 2; 2; 2; 3; 3; 3];
Y = [2; 3; 4; 1; 3; 4; 1; 2; 4];
Value = [6.9; 6.8; 8.1;7.2;11.7;16;22.6;20.5;18.1];
T = table(X,Y,Value);

% Get the position of the maximum Value in every group
[~,I] = splitapply(@max, T.Value, T.X); % I == [3; 3; 1]

% Get beginnings of every group
lastGroupEnd = find([1; diff(X)])-1; % lastGroupEnd == [0; 3; 6]

% Offset the maximum positions by group starts to get row indices in the original table
T2 = T(I + lastGroupEnd, :);
0 голосов
/ 02 июня 2019

Вы можете сделать это, используя цикл с уникальными X значениями:

X = [1; 1; 1; 2; 2; 2; 3; 3; 3];
Y = [2; 3; 4; 1; 3; 4; 1; 2; 4];
Value = [6.9; 6.8; 8.1;7.2;11.7;16;22.6;20.5;18.1];

uniqueX = unique(X); % Get 'X' unique values
maxidx = zeros(size(uniqueX));
for i = 1:length(uniqueX)
    xind = find(X == uniqueX(i)); % Find all indices of a unique 'X' value
    [~,vind] = max(Value(xind)); % Find index of max Value in 'xind' group
    maxidx(i) = xind(vind); % Get the index in the original group 
end

T(maxidx,:)

Вывод:

ans =
  3×3 table
    X    Y    Value
    _    _    _____
    1    4     8.1 
    2    4      16 
    3    1    22.6 
0 голосов
/ 02 июня 2019

Использование уникально и cumsum

X = [1; 1; 1; 2; 2; 2; 3; 3; 3];
Y = [2; 3; 4; 1; 3; 4; 1; 2; 4];
values = [6.9; 6.8; 8.1;7.2;11.7;16;22.6;20.5;18.1];

T = table(X,Y,values);

% Find number of categorical X and corresponding category X 
[count,category]=hist(X,unique(X));

% Starting offset index of each category, X = 2, offset is 3, X = 3, offset is 6
location = cumsum(count);

maxidx = zeros(1,numel(category));

for i = 1:numel(category)
    [~,maxidx(i)] = max(T(T.X == category(i) , :).values);
if i == 1
    % First category, no need offset 
else
    % Locate max index in whole table by adding offset to the initial index
    maxidx(i) = maxidx(i) + location(i-1);
end
end
T(maxidx,:)
%{
ans =

  3×3 table

    X    Y    values
    _    _    ______

    1    4      8.1 
    2    4       16 
    3    1     22.6 
    %}
...