1

我有一张带有 ID 和日期的表格。我想检索每个 ID 的最大日期的索引。

我最初的方法是: varfun(@max, table, 'Grouping Variables', 'Id', 'InputVariables','Date');

这显然给了我日期而不是索引。我注意到 max 函数在指定时将返回 maxvalue 和 maxindex: [max_val, max_idx] = max(values);

如何使用 max 定义匿名函数来检索 max_idx?然后我会在 var_fun 中使用它来获得我的结果。

我不想在 max() 上声明一个覆盖函数(而不是匿名函数):1.我正在使用脚本,不想创建另一个函数文件 2.我不愿意改变我的当前脚本到函数

谢谢百万人

4

2 回答 2

3

我假设您的Ids 是正整数,并且您的Dates 是 numbers

如果您想要每个 Id 的最大日期,这将是accumarray使用该max函数的完美案例。在下文中,我将使用f来表示传递给accumarray.

您想要最大值索引的事实使它有点棘手(而且更有趣!)。问题是与给定 ID 对应的日期被传递给f没有对其原始索引的任何引用。因此,一个f基于max不能帮助。但是您可以使索引“通过”accumarray作为日期的虚部

所以:如果您只想要每个 Id 的一个最大化索引(即使有多个):

result = accumarray(t.Id,...  %// col vector of Id's
    t.Date+1j*(1:size(t,1)).', ... %'// col vector of Dates (real) and indices (imag)
    [], ... %// default size for output
    @(x) imag(x(find(real(x)==max(real(x))),1))); %// function f

请注意,f这里的函数最大化部,然后提取包含原始索引的虚部。

或者,如果您想要每个 Id 的所有最大化索引:

result = accumarray(t.Id,...  %// col vector of Id's
    t.Date+1j*(1:size(t,1)).', ... %'// col vector of Dates (real) and indices (imag)
    [], ... %// default size for output
    @(x) {imag(x(find(real(x)==max(real(x)))))}); %// function f

如果您的Id 是字符串:使用 的第三个输出将它们转换为数字标签unique,然后按上述方式进行操作:

[~, ~, NumId] = unique(t.Id);

然后要么

result = accumarray(NumId,...  %// col vector of Id's
    t.Date+1j*(1:size(t,1)).', ... %'// col vector of Dates (real) and indices (imag)
    [], ... %// default size for output
    @(x) imag(x(find(real(x)==max(real(x))),1))); % function f

或者

result = accumarray(NumId,...  %// col vector of Id's
    t.Date+1j*(1:size(t,1)).', ... %'// col vector of Dates (real) and indices (imag)
    [], ... %// default size for output
    @(x) {imag(x(find(real(x)==max(real(x)))))}); %// function f
于 2015-02-09T22:11:36.727 回答
2

我认为这不是varfun正确的方法,因为

varfun(func,A)将函数func分别应用于表的每个变量A

仅当您想将其应用于多个列时,这才有意义。

简单的方法:

只需使用循环方法:首先使用 找到不同的 ID unique,然后为每个 ID 找到最大日期的索引。(这假设您的日期是可以直接使用比较的数字格式max。)我确实将您的变量重命名tablet,否则我们将覆盖内置函数table

uniqueIds = unique(t.Id);
for i = 1:numel(uniqueIds)
    equalsCurrentId = t.Id==uniqueIds(i); 
    globalIdxs = find(equalsCurrentId);
    [~, localIdxsOfMax] = max(t.Date(equalsCurrentId));
    maxIdxs{i} = globalIdxs(localIdxsOfMax);
end

正如您所提到的,您Ids实际上是字符串而不是数字,您将不得不更改行equalsCurrentId = t.Id==uniqueIds(i);

 equalsCurrentId = strcmp(t.Id, uniqueIds{i});

使用方法accumarray

如果您更喜欢更紧凑的风格,您可以使用受Luis Mendo答案启发的这个解决方案,它应该适用于数字和字符串 Id:

[uniqueIds, ~, global2Unique] = unique(t.Id);
maxDateIdxsOfIdxSubset = @(I) {I(nth_output(2, @max, t.Date(I)))};
maxIdxs = accumarray(global2Unique, 1:length(t.Id), [], maxDateIdxsOfIdxSubset);

这使用nth_outputgnovice绝佳答案

用法:

uniqueIds上述两种解决方案都将产生:具有相应cell-array的向量maxIdxs,其方式maxIdxs{i}是 的最大日期的索引uniqueIds(i)。如果您只想要一个索引,即使有多个条目达到最大值,也可以使用以下内容去除不需要的数据:

maxIdxs = cellfun(@(X) X(1), maxIdxs);
于 2015-02-09T21:43:06.177 回答