簡體   English   中英

使用dplyr從數據框中制作樣本

[英]Using dplyr to make sample from data frame

我有一個非常大的數據框(1500萬行),其格式如下:

df = data.frame(pnr = rep(500+2*(1:15),each=3), x = runif(3*15))

pnr是個人ID,x是一些數據。 我想抽樣10%的人。 在dplyr中有快速的方法嗎?

以下是解決方案,但是由於合並語句,它很慢

prns = as.data.frame(unique(df$prn))
names(prns)[1] = "prn"
prns$s = rbinom(nrow(prns),1,0.1)

df = merge(df,prns)
df2 = df[df$s==1,]

在基數R中,對10%的行進行采樣,向上舍入到下一行

> df[sample(nrow(df), ceiling(0.1*nrow(df)), FALSE), ]
##    pnr         x
## 16 512 0.9781232
## 21 514 0.5279925
## 33 522 0.8332834
## 14 510 0.7989481
## 4  504 0.7825318

或四舍五入到下一行

> df[sample(nrow(df), floor(0.1*nrow(df)), FALSE), ]
##    pnr           x
## 43 530 0.449985180
## 35 524 0.996350657
## 2  502 0.499871966
## 25 518 0.005199058

或取樣pnr色譜柱的10%,四舍五入

> sample(df$pnr, ceiling(0.1*length(df$pnr)), FALSE)
## [1] 530 516 526 518 514 

加:

如果您想對10%的人(唯一的pnr ID)進行抽樣,並返回這些人及其各自的數據,我認為您想要

> S <- sample(unique(df$pnr), ceiling(0.1*length(unique(df$pnr))), FALSE)
> df[df$pnr %in% S, ]
##    pnr         x
## 1  502 0.7630667
## 2  502 0.4998720
## 3  502 0.4839460
## 22 516 0.8248153
## 23 516 0.5795991
## 24 516 0.1572472

PS:我會等一個dplyr答案。 1500萬行上的速度可能會更快。

我實際上建議在“ dplyr”上使用“ data.table”包。 這是一個包含大量示例數據的示例(比您自己的1500萬行小很多)。

我還將展示一些正確和錯誤的方法:-)

這是示例數據。

library(data.table)
library(dplyr)
library(microbenchmark)
set.seed(1)
mydf <- DT <- data.frame(person = sample(10000, 1e7, TRUE),
                   value = runif(1e7))

我們還將創建一個“ data.table”並將鍵設置為“ person”。 創建“ data.table”不需要花費大量時間,但是可以設置鍵。

system.time(setDT(DT))
#    user  system elapsed 
#   0.001   0.000   0.001 

## Setting the key takes some time, but is worth it
system.time(setkey(DT, person)) 
#    user  system elapsed 
#   0.620   0.025   0.646

我無法想到一種比以下方法更有效的選擇“人”值的方法,因此我將其從基准中刪除了,它們對於所有方法都是通用的。

## Common to all tests...
A <- unique(mydf$person)
B <- sample(A, ceiling(.1 * length(A)), FALSE)

為了方便起見,將不同的測試表示為功能...

## Base R #1
fun1a <- function() {
  mydf[mydf$person %in% B, ]
}

## Base R #2--sometimes using `which` makes things quicker
fun1b <- function() {
  mydf[which(mydf$person %in% B), ]
}

## `filter` from "dplyr"
fun2 <- function() {
  filter(mydf, person %in% B)
}

## The "wrong" way to do this with "data.table"
fun3a <- function() {
  DT[which(person %in% B)]
}

## The "right" (I think) way to do this with "data.table"
fun3b <- function() {
  DT[J(B)]
}

現在,我們可以進行基准測試:

## The benchmarking
microbenchmark(fun1a(), fun1b(), fun2(), fun3a(), fun3b(), times = 20)
# Unit: milliseconds
#     expr       min        lq    median        uq       max neval
#  fun1a() 382.37534 394.27968 396.76076 406.92431 494.32220    20
#  fun1b() 401.91530 413.04710 416.38470 425.90150 503.83169    20
#   fun2() 381.78909 394.16716 395.49341 399.01202 417.79044    20
#  fun3a() 387.35363 397.02220 399.18113 406.23515 413.56128    20
#  fun3b()  28.77801  28.91648  29.01535  29.37596  42.34043    20

看看正確使用“ data.table”獲得的性能! 所有其他方法都非常快。


summary顯示的結果是相同的。 (由於已排序,因此“ data.table”解決方案的行順序將有所不同。)

summary(fun1a())
#      person         value         
#  Min.   :  16   Min.   :0.000002  
#  1st Qu.:2424   1st Qu.:0.250988  
#  Median :5075   Median :0.500259  
#  Mean   :4958   Mean   :0.500349  
#  3rd Qu.:7434   3rd Qu.:0.749601  
#  Max.   :9973   Max.   :1.000000  

summary(fun2())
#      person         value         
#  Min.   :  16   Min.   :0.000002  
#  1st Qu.:2424   1st Qu.:0.250988  
#  Median :5075   Median :0.500259  
#  Mean   :4958   Mean   :0.500349  
#  3rd Qu.:7434   3rd Qu.:0.749601  
#  Max.   :9973   Max.   :1.000000  

summary(fun3b())
#      person         value         
#  Min.   :  16   Min.   :0.000002  
#  1st Qu.:2424   1st Qu.:0.250988  
#  Median :5075   Median :0.500259  
#  Mean   :4958   Mean   :0.500349  
#  3rd Qu.:7434   3rd Qu.:0.749601  
#  Max.   :9973   Max.   :1.000000 

如果您不一定需要完全隨機的樣本,則可以

filter(df, pnr %% 10 ==0).

每10個人要花費一次(更改為==1 ,您可以獲得10個不同的樣本,...)。 您可以通過隨機地重新分配ID來使其隨機-對於玩具示例,使用sample(15)[(df$pnr-500)/2]來做到這一點相當簡單-將pnr的映射pnr映射到適合sample的集合上在現實世界中可能不太容易。

暫無
暫無

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

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