2015-06-20 80 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不會做任何事情,只需對數據進行重新排序,使其看起來像您想要的輸出。