我正在尝试运行使用该splitapply
函数的其他人的 Matlab 代码,该函数仅在 R2018a 中可用。我目前正在使用 R2015a;是否有一个简单的(尽管效率较低)替代实现可以达到可以(暂时)使用的相同目的?
3 回答
记录的splitapply
用法还依赖于findgroups
. 这两个都在 R2015b [1]中实现。
您可以使用第三个输出unique
代替findgroups
,并使用一个简单的循环代替splitapply
。这是一个假设data
是列向量的示例,您可以轻松地将其调整为适用于矩阵数据。
% With splitapply
g = findgroups( data );
m = splitapply( @mean, data, g ); % Your function in place of mean here
% Without splitapply (pre-R2015b)
[~, ~, g] = unique( data ); % Get group indices
m = zeros(max(g), 1); % Initialise the output matrix
for ii = 1:max(g)
m(ii) = mean( data( g == ii ) ); % Your function in place of mean here
end
通过一些快速测试,我发现这些方法在合理大小的数组上的速度相当。对于 ~100 个组和 ~1e6 个元素,data
我发现循环方法慢了 4 倍,但仍然相当快。
[1] 注意:MathWorks 文档默认为最新版本,这就是您认为splitapply
在 R2018a 中引入的原因。但是,在每个函数的文档页面的底部,它会说明它是何时引入的。在 的情况下splitapply
,我们看到“在 R2015b 中引入”。
实际上,splitapply
已经在 R2015b 中引入。
无论如何,如splitapply文档中所述,该功能结合了 Split-Apply-Combine 工作流程中的两个步骤
下图(来自splitapply
在线文档描述了该过程:
基本上splitapply
使用函数findgroups对输入数据进行分组,然后对每组数据应用一个函数。
不幸的是,R2015b 中也findgroups
引入了它,因此主要问题是找到实现它的方法。
实现“通用”版本findgroups
可能需要大量时间才能使其能够处理几种不同类型的数据集。
刚开始,您可以开始以与您必须使用的特定数据集匹配的形式实现它。
基本上,您可以使用unique函数来实现它的简化版本。
这个想法是使用它来检索:
- 数据集中唯一条目的列表:这些将是组
- 对应于这些组的数据集中条目的索引
获得数据集中组的索引后,您可以使用它们来下选数据集的值,并将它们用作您需要应用的函数的输入。
在下文中,您可以找到一个可能实现的示例,该示例重现了 .com 的在线帮助中提供的示例splitapply
。
当然,这不是使用“每个”数据集的“通用”实现,实际上它适用于示例的特定输入,但我希望它可以作为一个起点。
splitapply的在线示例
load patients
meanBMIFcn = @(h,w)mean((w ./ (h.^2)) * 703);
DT = table(Height,Weight);
GT = table(Gender,Smoker);
[G,results] = findgroups(GT);
meanBMI = splitapply(meanBMIFcn,DT,G);
results.meanBMI = meanBMI
输出
results=4×3 table
Gender Smoker meanBMI
________ ______ _______
'Female' false 21.672
'Female' true 21.669
'Male' false 26.578
'Male' true 26.458
一个可能的实现
clear w
% Find the unique entries in the first dataset
[uni_list_1,~,uni_idx_1]=unique(Gender)
n_group_1=length(uni_list_1)
% Find the unique entries in the second dataset
[uni_list_2,~,uni_idx_2]=unique(Smoker)
n_group_2=length(uni_list_2)
% Get the indices of the occurrencies of the combinatin of the two
% entities
for g1=1:length(uni_list_1)
for g2=1:length(uni_list_2)
data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))])=(uni_idx_1 == g1) & (uni_idx_2 == g2)
end
end
% Define the function to be applied
meanBMIFcn = @(h,w)mean((w ./ (h.^2)) * 703);
% Extract the data matching the desired conditions and use them as input to
% the disired function
for g1=1:length(uni_list_1)
for g2=1:length(uni_list_2)
height=Height(data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))]));
weight=Weight(data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))]));
result.data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))])=meanBMIFcn(height,weight)
end
end
输出
输出采用结构形式,其字段是组和附加条件
>> result
result =
data_set: [1x1 struct]
>> result.data_set
ans =
Female: [1x1 struct]
Male: [1x1 struct]
>> result.data_set.Female
ans =
cond_0: 21.6721
cond_1: 21.6686
>> result.data_set.Male
ans =
cond_0: 26.5775
cond_1: 26.4584
您可以从统计工具箱中查看grpstats 。