簡體   English   中英

dplyr sample_n其中n是分組變量的值

[英]dplyr sample_n where n is the value of a grouped variable

我有以下分組數據框,我想使用函數dplyr::sample_n從每個組的數據框中提取行。 我想在每個組中使用分組變量NDG的值作為從每個組中提取的行數。

> 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 有點hackish代碼

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

返回以下警告消息

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 (在適當的環境中)被評估為c(1,1,1)c(2,2,2) ,因此1:NDG返回上述警告。


關於為什么我得到錯誤,我知道Hadley用於方法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頁面上找到。 因此我得到了錯誤,因為sample_n.grouped_df無法找到變量NGD因為它沒有查找正確的環境。

因此,是否有一種在dg上使用sample_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

通過對每組使用隨機抽樣?

一個可能的答案,但我不相信它是最佳答案:用dplyr::sample_frac (和1的一小部分)置換數據幀的行,然后切片所需的行數:

> 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

而且我想我可以在必要時編寫一個函數來在一行中執行此操作。

這是一個替代答案,雖然上面的一個似乎很好:

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不做任何事情。

我使用分組dfs遇到了同樣的問題,並記得在purrr有一個非常優雅的方法來執行此purrr ,如本非常有用的教程中所述

library(purrr)

dg.tmp %>% 
  nest(-GLB, -NDG) %>% 
  mutate(data = map2(data, NDG, sample_n)) %>% 
  unnest

一個優點是它不需要像sample_frac那樣排列所有數據行,這對於大型數據幀來說可能是非常昂貴的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM