統計抽樣

R與統計抽樣

常見的抽樣方法

常見的抽樣方法可分為機率抽樣法非機率抽樣法,還有結合兩者特性的配對抽樣法。 配對抽樣(matched sampling )是一種特殊的抽樣方法,通常用於病例對照研究或其他需要匹配樣本的研究中。在這種方法中,每個目標個體(例如病例)都會被匹配到一組以上對照個體(例如對照組),通常病例組和對照組的比例為1:4,並且這些對照個體在某些關鍵變量上與目標個體相似(例如年齡、性別)。這種方法類似於 分層隨機抽樣(Stratified Sampling)配額抽樣(Quota Sampling) 的結合,但更具體地應用了配對策略

機率抽樣法 非機率抽樣法

簡單隨機抽樣(Simple Random Sampling)

  • 母體中每個單位被抽中的機率是相等的

  • 抽樣過程是隨機的,每個單位都有相同的機會被選為受訪者

便利抽樣(Convenience Sampling)

  • 選擇最容易獲得的對象作為樣本

  • 操作簡單,成本低,但可能存在偏差

系統抽樣(Systematic Sampling)

  • 根據一定的間隔從母體中選取單位,形成樣本

  • 抽樣過程簡單,成本較低

判斷抽樣(Judgement Sampling)

  • 根據研究者的判斷選擇具有代表性的對象作為樣本

  • 需要研究者有豐富的經驗和專業知識

分層隨機抽樣(Stratified Random Sampling)

  • 將母體劃分為幾個層次,然後在每個層次中進行簡單隨機抽樣

  • 可以提高樣本的代表性,減少抽樣誤差

配額抽樣(Quota Sampling)

  • 根據母體的特徵劃分層次,然後在每個層次中按比例選取樣本

  • 操作簡單,但可能存在抽樣偏差

群集抽樣(Cluster Sampling)

  • 將母體劃分為若干個群集,然後隨機抽取部分群集,對抽中的群集進行全數調查

  • 適用於母體分散的情況,可以減少調查成本

滾雪球抽樣(Snowball Sampling)

  • 從一個或幾個對象開始,逐步擴大樣本的範圍

  • 適用於尋找隱藏人群,但可能存在偏差

簡單隨機抽樣(Simple Random Sampling)

1.sample() :

功能: R 中最基本的隨機抽樣函數,可以從向量中隨機抽取元素

sample(x, size, replace = FALSE, prob = NULL)

參數:

  • x:要抽樣的對象,通常是一個向量或數列。

  • size:要抽取的樣本數。

  • replace:是否允許重複抽樣。預設為 FALSE

  • prob:每個元素被選中的概率(可選)。

範例:

# 從 1 到 100 中隨機抽取 10 個數字
sample(1:100, 10)
 [1] 99 30 40 35 84 74 55 81 60 25

2.dplyr::sample_n() :

功能: dplyr 套件中的函數,用於從數據框中隨機抽取固定數量的行。

sample_n(tbl, size, replace = FALSE, weight = NULL)

參數:

  • tbl:要抽樣的資料集(data.frame)。

  • size:要抽取的樣本數。

  • replace:是否允許重複抽樣。預設為 FALSE

  • weight:每個元素被權重的比例(可選)。 範例:

library(dplyr)
# 從數據框 df 中隨機抽取 5 行
(sampled_df <- iris %>% sample_n(5))
  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          6.9         3.1          5.1         2.3  virginica
2          5.7         2.9          4.2         1.3 versicolor
3          6.9         3.2          5.7         2.3  virginica
4          6.7         3.1          4.4         1.4 versicolor
5          6.8         3.0          5.5         2.1  virginica

3.dplyr::sample_frac() :

功能: dplyr 套件中的函數,用於從數據框中按比例隨機抽樣。

sample_n(tbl, size = 1, replace = FALSE, weight = NULL)

參數:

  • tbl:要抽樣的資料集(data.frame)。

  • size:要抽取的樣本數。

  • replace:是否允許重複抽樣。預設為 FALSE

  • weight:每個元素被權重的比例(可選)。 範例:

library(dplyr)
# 從數據框 df 中隨機抽取 50% 的行
(sampled_df <- iris %>% sample_frac(0.1))
   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1           6.0         2.7          5.1         1.6 versicolor
2           6.7         3.0          5.2         2.3  virginica
3           5.7         2.6          3.5         1.0 versicolor
4           4.6         3.6          1.0         0.2     setosa
5           6.2         2.9          4.3         1.3 versicolor
6           5.3         3.7          1.5         0.2     setosa
7           5.9         3.2          4.8         1.8 versicolor
8           6.2         2.2          4.5         1.5 versicolor
9           6.0         2.2          4.0         1.0 versicolor
10          6.7         3.1          5.6         2.4  virginica
11          5.9         3.0          5.1         1.8  virginica
12          6.1         3.0          4.6         1.4 versicolor
13          5.6         2.7          4.2         1.3 versicolor
14          4.4         3.0          1.3         0.2     setosa
15          5.0         3.4          1.6         0.4     setosa

系統抽樣(Systematic Sampling)

善用seq(),進行產生規則rows序列,再利用資料框擷取抽樣出等距的樣本數 seq(from, to, by, length.out, along.with, ...) 參數:

  • from:序列的起始值

  • to:序列的結束值。

  • by:序列的間隔值。

  • length.out:序列的數量值

  • along.with:與length.out互斥的參數,不能同時使用,along.with 參數是用來指定生成的序列應該與另一個對象(如向量)的長度相同

ind <- seq(from = 1,to=50 ,by=5)
df  <-  iris
df[ind,]
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1           5.1         3.5          1.4         0.2  setosa
6           5.4         3.9          1.7         0.4  setosa
11          5.4         3.7          1.5         0.2  setosa
16          5.7         4.4          1.5         0.4  setosa
21          5.4         3.4          1.7         0.2  setosa
26          5.0         3.0          1.6         0.2  setosa
31          4.8         3.1          1.6         0.2  setosa
36          5.0         3.2          1.2         0.2  setosa
41          5.0         3.5          1.3         0.3  setosa
46          4.8         3.0          1.4         0.3  setosa

分層隨機抽樣(Stratified Random Sampling)

1. 使用splitstackshape套件

library(splitstackshape)
# 使用 splitstackshape 進行分層抽樣,每個層內抽取 5 個樣本
stratified(iris, "Species", size = 5)
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
           <num>       <num>        <num>       <num>     <fctr>
 1:          4.9         3.1          1.5         0.1     setosa
 2:          5.1         3.8          1.5         0.3     setosa
 3:          5.0         3.4          1.6         0.4     setosa
 4:          5.0         3.6          1.4         0.2     setosa
 5:          5.0         3.2          1.2         0.2     setosa
 6:          7.0         3.2          4.7         1.4 versicolor
 7:          5.6         2.5          3.9         1.1 versicolor
 8:          5.9         3.0          4.2         1.5 versicolor
 9:          5.8         2.6          4.0         1.2 versicolor
10:          6.3         3.3          4.7         1.6 versicolor
11:          6.8         3.0          5.5         2.1  virginica
12:          6.7         3.0          5.2         2.3  virginica
13:          7.3         2.9          6.3         1.8  virginica
14:          6.1         3.0          4.9         1.8  virginica
15:          7.7         2.6          6.9         2.3  virginica
# 或者按比例抽樣
stratified(iris, "Species", size = 0.1)
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
           <num>       <num>        <num>       <num>     <fctr>
 1:          5.4         3.4          1.7         0.2     setosa
 2:          4.4         2.9          1.4         0.2     setosa
 3:          5.4         3.4          1.5         0.4     setosa
 4:          5.1         3.3          1.7         0.5     setosa
 5:          4.8         3.4          1.9         0.2     setosa
 6:          6.1         2.9          4.7         1.4 versicolor
 7:          5.8         2.7          3.9         1.2 versicolor
 8:          5.0         2.0          3.5         1.0 versicolor
 9:          4.9         2.4          3.3         1.0 versicolor
10:          6.1         2.8          4.0         1.3 versicolor
11:          6.9         3.1          5.1         2.3  virginica
12:          6.3         2.7          4.9         1.8  virginica
13:          6.5         3.0          5.8         2.2  virginica
14:          6.0         2.2          5.0         1.5  virginica
15:          6.7         3.3          5.7         2.1  virginica

2. 使用dplyr::group_by() + dplyr::sample_n() 或 sample_frac()

library(dplyr)

# 分層隨機抽樣 - 每組別中抽取 5 個樣本
iris %>%
  group_by(Species) %>%    # 按Species分組
  sample_n(5)             # 在每個組別中隨機抽取 5 個樣本
# A tibble: 15 × 5
# Groups:   Species [3]
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species   
          <dbl>       <dbl>        <dbl>       <dbl> <fct>     
 1          5.4         3.4          1.5         0.4 setosa    
 2          4.6         3.6          1           0.2 setosa    
 3          4.6         3.1          1.5         0.2 setosa    
 4          5.7         4.4          1.5         0.4 setosa    
 5          4.8         3.4          1.6         0.2 setosa    
 6          6.3         2.5          4.9         1.5 versicolor
 7          5.6         3            4.1         1.3 versicolor
 8          5.1         2.5          3           1.1 versicolor
 9          5.9         3            4.2         1.5 versicolor
10          4.9         2.4          3.3         1   versicolor
11          6.1         2.6          5.6         1.4 virginica 
12          6.7         3.3          5.7         2.5 virginica 
13          6.7         3.1          5.6         2.4 virginica 
14          6.5         3.2          5.1         2   virginica 
15          6.3         2.5          5           1.9 virginica 
# 或者按比例抽樣
iris %>%
  group_by(Species) %>%    # 按Species分組
  sample_frac(0.1)        # 在每個組別中隨機抽取 10% 的樣本
# A tibble: 15 × 5
# Groups:   Species [3]
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species   
          <dbl>       <dbl>        <dbl>       <dbl> <fct>     
 1          4.4         2.9          1.4         0.2 setosa    
 2          5.4         3.9          1.7         0.4 setosa    
 3          4.8         3.4          1.9         0.2 setosa    
 4          4.8         3.1          1.6         0.2 setosa    
 5          4.3         3            1.1         0.1 setosa    
 6          5.6         3            4.5         1.5 versicolor
 7          6.1         2.9          4.7         1.4 versicolor
 8          5.8         2.7          4.1         1   versicolor
 9          5.7         2.6          3.5         1   versicolor
10          6.3         3.3          4.7         1.6 versicolor
11          6.7         3.3          5.7         2.5 virginica 
12          6.1         3            4.9         1.8 virginica 
13          5.8         2.8          5.1         2.4 virginica 
14          6.7         2.5          5.8         1.8 virginica 
15          7.2         3            5.8         1.6 virginica 

群集抽樣(Cluster Sampling)

1. 使用dplyr::group_by+ dplyr:: filter()

library(dplyr)
# 假設 df 是數據框,並且它有一個變量 'cluster' 來標識群集
df <- data.frame(cluster = rep(1:10, each = 10), value = rnorm(100))

# 隨機選擇群集
set.seed(123)  # 設置隨機種子以確保可重現性

# 使用 dplyr 進行群集抽樣
set.seed(123)
cluster_sample <- df %>%
  group_by(cluster) %>%
  filter(cluster %in% sample(unique(df$cluster), size = 3))

cluster_sample
# A tibble: 20 × 2
# Groups:   cluster [2]
   cluster   value
     <int>   <dbl>
 1       2 -0.500 
 2       2  1.76  
 3       2 -0.802 
 4       2  0.912 
 5       2  0.585 
 6       2 -1.05  
 7       2  1.30  
 8       2 -1.71  
 9       2 -1.49  
10       2 -1.54  
11       5 -0.943 
12       5 -0.0456
13       5  1.01  
14       5  0.259 
15       5 -0.820 
16       5 -1.12  
17       5  0.567 
18       5  1.50  
19       5 -2.26  
20       5  0.140 

1. 使用 sampling 套件的 cluster() 函數

# 安裝並載入 sampling 套件
#install.packages("sampling")
library(sampling)

# 使用 sampling 包進行群集抽樣
set.seed(123)
clusters <- cluster(iris, clustername = "Species", size = 1, method = "srswor")

# 獲取抽樣數據
cluster_sample <- getdata(iris, clusters)

配對抽樣(match Sampling)

# 安裝並載入 MatchIt 套件
#install.packages("MatchIt")
library(MatchIt)

#建立檔案
health_data <- data.frame("disease"= sample(x=c(1,0), size= 1500, replace = T, prob = c(1,12)),
                          "gender" = sample(x=c(1,0), size= 1500, replace = T, prob = c(5.5,4.5)),
                          "age"= sample(x=c(35:70), size= 1500, replace = T))

# 進行1:4的匹配
match.out <- matchit(disease ~ age + gender, data = health_data, ratio = 4, method = "nearest")

# 查看匹配後的結果
summary(match.out)

Call:
matchit(formula = disease ~ age + gender, data = health_data, 
    method = "nearest", ratio = 4)

Summary of Balance for All Data:
         Means Treated Means Control Std. Mean Diff. Var. Ratio eCDF Mean
distance        0.0697        0.0693          0.0754     1.0040    0.0233
age            52.9615       52.7192          0.0231     0.9931    0.0179
gender          0.5096        0.5458         -0.0725          .    0.0362
         eCDF Max
distance   0.0675
age        0.0426
gender     0.0362

Summary of Balance for Matched Data:
         Means Treated Means Control Std. Mean Diff. Var. Ratio eCDF Mean
distance        0.0697        0.0697          0.0001     1.0074    0.0000
age            52.9615       52.9591          0.0002     1.0068    0.0001
gender          0.5096        0.5096          0.0000          .    0.0000
         eCDF Max Std. Pair Dist.
distance   0.0024          0.0001
age        0.0024          0.0002
gender     0.0000          0.0000

Sample Sizes:
          Control Treated
All          1396     104
Matched       416     104
Unmatched     980       0
Discarded       0       0
#提取匹配的對照組和患者組"
matched_data <- match.data(match.out) %>%  select(-c("distance","weights", "subclass"))

# 患者組
patients <- matched_data[matched_data$disease == 1, ]
# 對照組
controls <- matched_data[matched_data$disease == 0, ]

head(patients)
   disease gender age
4        1      0  36
10       1      1  68
19       1      1  41
23       1      1  62
30       1      0  55
86       1      0  37
head(controls)
  disease gender age
1       0      0  45
2       0      1  62
3       0      1  52
5       0      0  55
8       0      1  62
9       0      0  58
#配對檢定
#t.test(age ~ disease, data = matched_data)
#table(matched_data$gender,matched_data$disease) %>% chisq.test()