创建一个在多个变量之间平衡的子集

时间:2014-05-15 16:59:53

标签: r subset

为了说明我的问题,一个虚拟的例子:我有一个16行的数据集(这些代表试验)和3列(试验难度,标签X和标签Y)。标签X是4级(1-4)的因子,标签Y是2级的因子("女性","男性")。例如:

        difficulty    X    Y
trial1   3.0           1    male
trial2   1.4           1    male
trial3   2.1           1    female
trial4   1.5           1    female
trial5   0.3           2    male
trial6   1.2           2    male
trial7   3.0           2    female
trial8   1.6           2    female
trial9   0.8           3    male
trial10  1.4           3    male
trial11  2.8           3    female
trial12  1.5           3    female
trial13  0.3           4    male
trial14  1.2           4    male
trial15  3.0           4    female
trial16  1.6           4    female

我想在总共16项试验中创建8项试验的子集;应符合以下标准的子集:

  1. 在标签X的四个级别内有相同数量的试验
  2. 在标签Y的两个级别内有相同数量的试验(并且在标签X的四个级别内,每个级别的标签Y也应该有相同数量的试验)
  3. 试验难度变量(数字,范围从0到3)应尽可能接近1.5
  4. 对于我的例子,这个虚拟例子中的理想集合是:

            difficulty    X    Y
    trial2   1.4           1    male
    trial4   1.5           1    female
    trial6   1.2           2    male
    trial8   1.6           2    female
    trial10  1.4           3    male
    trial12  1.5           3    female
    trial14  1.2           4    male
    trial16  1.6           4    female
    

    该子集每个X级别有2个试验,每个X级别有相同数量的雌性和雄性,而所有试验的难度值都尽可能接近1.5。

    我的尝试是使用了许多嵌套的whileif循环,但我不确定如何同时检查两个变量(此时我正在循环直到X完成,然后循环直到Y完成,然后循环直到再次满足X,等等。这是正确的做法,还是会有更合理的方法来做到这一点?

1 个答案:

答案 0 :(得分:3)

以下代码假设您的数据框名为dat。代码添加一个新变量difficulty.scaled,等于difficulty与1.5的偏差,然后按X和Y的值对数据进行分组,然后在每个组中选择绝对值为{{1最接近0的(即最接近1.5的difficulty.scaled)。

您可以调整difficulty函数的probs参数,以选择所需的每个子组的百分比。在这种情况下,我已经选择了每个子组中50%的行(即,代表quantileX的每个组合的行的50%。)

Y

对于您在上面粘贴的数据(我已将试用版转换为变量),输出如下:

library(dplyr)  # Install the dplyr package if you don't already have it
dat2 = dat %.%
         mutate(difficulty.scaled=difficulty - 1.5) %.%
         group_by(X, Y) %.%
         filter(abs(difficulty.scaled) < quantile(abs(difficulty.scaled), .5))

您提供的数据对 tnum difficulty X Y difficulty.scaled 1 trial2 1.4 1 male -0.1 2 trial4 1.5 1 female 0.0 3 trial6 1.2 2 male -0.3 4 trial8 1.6 2 female 0.1 5 trial10 1.4 3 male -0.1 6 trial12 1.5 3 female 0.0 7 trial14 1.2 4 male -0.3 8 trial16 1.6 4 female 0.1 X的每种组合都有相同数量的观察结果。如果您的实际数据在这些变量上不平衡,那么您可以选择特定数量的行,而不是选择每个子组中的行百分比。下面的代码选择每个子组中绝对值最低Y的{​​{1}}行。这样,即使您的完整数据集不是,您的子集也会得到平衡(只要ndifficulty.scaled的每个组合至少有n行数据。

X

Y可确保返回准确的n=1 dat2 = dat %.% mutate(difficulty.scaled=difficulty - 1.5) %.% group_by(X, Y) %.% filter(rank(abs(difficulty.scaled), ties.method="first") <= n) 行,即使有多个行具有相同的绝对值ties.method="first"

更新:如何将子集化数据划分为训练和测试集。

假设n是您的平衡子集,您可以将其划分为训练和测试子集,如下所示:

difficulty.scaled

这将为每个子组返回10个随机采样的行。只需将此值设置为训练样本中每个子组的任意行数。请注意,您不需要按X和Y分组来创建训练样本。这是因为当您创建dat2时,# Note that you need to use %>% instead of %.% train = dat2 %>% do(sample_n(., 10)) dat2添加了dplyr继续识别的分组属性。请dat2查看此内容。

dplyr是一个通用函数,允许您对str(dat2)内的数据帧执行任意操作。句点do是一种&#34;代词&#34;表示数据框(在这种情况下为dplyr)。这仅适用于.而不是dat2。 (%>%处于正在开发阶段,正在从%.%过渡到dplyr以进行链接操作,因此从现在开始使用%.%可能是最好的。)

%>%