Saya memiliki kumpulan data seperti:

df <- tibble(
  id = 1:18,
  class = rep(c(rep(1,3),rep(2,2),3),3),
  var_a = rep(c("a","b"),9)
)

# A tibble: 18 x 3
      id cluster var_a
   <int>   <dbl> <chr>
 1     1       1 a    
 2     2       1 b    
 3     3       1 a    
 4     4       2 b    
 5     5       2 a    
 6     6       3 b    
 7     7       1 a    
 8     8       1 b    
 9     9       1 a    
10    10       2 b    
11    11       2 a    
12    12       3 b    
13    13       1 a    
14    14       1 b    
15    15       1 a    
16    16       2 b    
17    17       2 a    
18    18       3 b 

Dataset tersebut berisi sejumlah observasi pada beberapa kelas. Kelas tidak seimbang. Pada contoh di atas dapat kita lihat, bahwa kelas 3 hanya ada 3 observasi, sedangkan kelas 2 ada 6 observasi dan kelas 1 ada 9 observasi.

Sekarang saya ingin secara otomatis menyeimbangkan dataset itu sehingga semua kelas memiliki ukuran yang sama. Jadi saya ingin kumpulan data 9 baris, 3 baris di setiap kelas. Saya dapat menggunakan fungsi sample_n dari dplyr untuk melakukan pengambilan sampel seperti itu.

Saya mencapainya dengan terlebih dahulu menghitung ukuran kelas terkecil ..

min_length <- as.numeric(df %>% 
  group_by(class) %>% 
  summarise(n = n()) %>% 
  ungroup() %>% 
  summarise(min = min(n)))

..dan kemudian terapkan fungsi sample_n:

set.seed(1)
df %>% group_by(cluster) %>% sample_n(min_length)

# A tibble: 9 x 3
# Groups:   cluster [3]
     id cluster var_a
  <int>   <dbl> <chr>
1    15       1 a    
2     7       1 a    
3    13       1 a    
4     4       2 b    
5     5       2 a    
6    17       2 a    
7    18       3 b    
8     6       3 b    
9    12       3 b    

Saya bertanya-tanya apakah mungkin melakukan itu (menghitung ukuran kelas terkecil dan kemudian mengambil sampel) sekaligus?

0
symbolrush 3 September 2020, 16:48

1 menjawab

Jawaban Terbaik

Anda dapat melakukannya dalam satu langkah, tetapi sedikit curang:

set.seed(42)
df %>%
  group_by(class) %>%
  sample_n(min(table(df$class))) %>%
  ungroup()
# # A tibble: 9 x 3
#      id class var_a
#   <int> <dbl> <chr>
# 1     1     1 a    
# 2     8     1 b    
# 3    15     1 a    
# 4     4     2 b    
# 5     5     2 a    
# 6    11     2 a    
# 7    12     3 b    
# 8    18     3 b    
# 9     6     3 b    

Saya katakan "curang" karena biasanya Anda tidak ingin referensi df$ dari dalam pipa. Namun, karena properti mereka yang kita cari adalah seluruh frame tetapi fungsi table hanya melihat satu grup pada satu waktu, kita perlu sedikit mengesampingkannya.

Seseorang bisa melakukannya

df %>%
  mutate(mn = min(table(class))) %>%
  group_by(class) %>%
  sample_n(mn[1]) %>%
  ungroup()
# # A tibble: 9 x 4
#      id class var_a    mn
#   <int> <dbl> <chr> <int>
# 1    14     1 b         3
# 2    13     1 a         3
# 3     7     1 a         3
# 4     4     2 b         3
# 5    16     2 b         3
# 6     5     2 a         3
# 7    12     3 b         3
# 8    18     3 b         3
# 9     6     3 b         3

Meskipun saya tidak berpikir itu lebih elegan/dapat dibaca.

1
r2evans 3 September 2020, 13:58