2015-06-20 79 views
3

我有以下分组数据框,并且我想使用函数dplyr::sample_n从这个数据框中为每个组提取行。我想使用每个组中分组变量NDG的值作为从每个组中提取的行数。dplyr sample_n其中n是分组变量的值

> dg.tmp <- structure(list(Gene = c("CAMK1", "GHRL", "TIMP4", "CAMK1", "GHRL", 
"TIMP4", "ARL8B", "ARPC4", "SEC13", "ARL8B", "ARPC4", "SEC13" 
), GLB = c(3, 3, 3, 3, 3, 3, 10, 10, 10, 10, 10, 10), NDG = c(1, 
1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2)), class = c("tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -12L), .Names = c("Gene", "GLB", 
"NDG")) 

> dg <- dg.tmp %>% 
    dplyr::group_by(GLB,NDG) 

> dg 
Source: local data frame [12 x 3] 
Groups: GLB, NDG 

     Gene GLB NDG 
1 A4GNT 3 1 
2 ABTB1 3 1 
3  AHSG 3 1 
4 A4GNT 3 2 
5 ABTB1 3 2 
6  AHSG 3 2 
7 AADAC 10 1 
8 ABHD14B 10 1 
9 ACVR2B 10 1 
10 AADAC 10 2 
11 ABHD14B 10 2 
12 ACVR2B 10 2 

例如,假设正确的随机选择,我想要的代码

> dg %>% dplyr::sample_n(NDG) 

输出:

Source: local data frame [6 x 3] 
Groups: GLB, NDG 

     Gene GLB NDG 
1 A4GNT 3 1 
2 A4GNT 3 2 
3 ABTB1 3 2 
4 AADAC 10 1 
5 AADAC 10 2 
6 ABHD14B 10 2 

但是,它提供了以下错误:

Error in eval(expr, envir, enclos) : object 'NDG' not found 

作为比较, dplyr::slice给出正确的输出,当我使用的代码

> dg %>% dplyr::slice(1:unique(NDG)) 

在这种情况下使用unique,但是,代码

> dg %>% dplyr::slice(1:NDG) 

返回以下警告消息稍有hackish的

Warning messages: 
1: In slice_impl(.data, dots) : 
    numerical expression has 3 elements: only the first used 
2: In slice_impl(.data, dots) : 
    numerical expression has 3 elements: only the first used 
3: In slice_impl(.data, dots) : 
    numerical expression has 3 elements: only the first used 
4: In slice_impl(.data, dots) : 
    numerical expression has 3 elements: only the first used 

很明显,因为NDG正在评估(在适当的环境ronment)为c(1,1,1)c(2,2,2),因此1:NDG返回上述警告。


至于为什么我得到的错误,我知道哈德利使用该方法sample_n.grouped_df代码

sample_n.grouped_df <- function(tbl, size, replace = FALSE, weight = NULL, 
    .env = parent.frame()) { 

    assert_that(is.numeric(size), length(size) == 1, size >= 0) 
    weight <- substitute(weight) 

    index <- attr(tbl, "indices") 
    sampled <- lapply(index, sample_group, frac = FALSE, 
    tbl = tbl, size = size, replace = replace, weight = weight, .env = .env) 
    idx <- unlist(sampled) + 1 

    grouped_df(tbl[idx, , drop = FALSE], vars = groups(tbl)) 
} 

,可以在相关Github page被发现。因此,我获得了错误,因为sample_n.grouped_df找不到变量NGD,因为它没有在正确的环境中查找。

因此,是有关于使用dgsample_n的一种巧妙的方法,通过使用对每个组随机采样得到

Source: local data frame [6 x 3] 
Groups: GLB, NDG 

     Gene GLB NDG 
1 A4GNT 3 1 
2 A4GNT 3 2 
3 ABTB1 3 2 
4 AADAC 10 1 
5 AADAC 10 2 
6 ABHD14B 10 2 

+0

您的示例df'dg'返回错误 – user227710

+0

感谢您的编辑。事实证明,在分组数据帧中使用'dput'并将代码输入回终端会出错,因为它找不到分组变量的名称。例如,将'dput(dg)'的输出复制并粘贴到控制台中会导致错误'object'GLB'not found'。奇怪... – AJP123

回答

3

一个可能的答案,但我不相信这是最佳的答案:置换数据帧的行与dplyr::sample_frac(和一个分数),然后切片所需的行数:

> set.seed(1) 
> dg %>% 
     dplyr::sample_frac(1) %>% 
     dplyr::slice(1:unique(NDG)) 

这给出了正确的输出。

Source: local data frame [6 x 3] 
Groups: GLB, NDG 

    Gene GLB NDG 
1 A4GNT 3 1 
2 AHSG 3 2 
3 A4GNT 3 2 
4 ACVR2B 10 1 
5 AADAC 10 2 
6 ACVR2B 10 2 

而且我想我可以编写一个函数在必要时在一行中执行此操作。

2

这里有一个备选答案,虽然上面的一个似乎很动听:

dg %>% 
    sample_frac(1) %>% 
    filter(row_number() <= NDG) %>% 
    arrange(NDG) 

Source: local data frame [6 x 3] 
Groups: GLB, NDG 

    Gene GLB NDG 
1 AHSG 3 1 
2 ABTB1 3 2 
3 AHSG 3 2 
4 ABHD14B 10 1 
5 AADAC 10 2 
6 ABHD14B 10 2 

sample_frac重新排序数据帧,并指派新的行数到各组,然后你只需要行的第一NDG数。 arrange不会做任何事情,只需对数据进行重新排序,使其看起来像您想要的输出。