Cara menggunakan fungsi 'sapuan'

100

Ketika saya melihat sumber Paket R, saya melihat fungsi yang sweepdigunakan cukup sering. Kadang-kadang digunakan ketika fungsi yang lebih sederhana sudah cukup (misalnya, apply), di lain waktu, tidak mungkin untuk mengetahui dengan tepat apa yang dilakukannya tanpa menghabiskan cukup banyak waktu untuk melangkah melalui blok kode di dalamnya.

Fakta bahwa saya dapat mereproduksi sweepefek menggunakan fungsi yang lebih sederhana menunjukkan bahwa saya tidak memahami sweepkasus penggunaan inti, dan fakta bahwa fungsi ini sering digunakan menunjukkan bahwa ini cukup berguna.

Isi:

sweepadalah fungsi di perpustakaan standar R; argumennya adalah:

sweep(x, MARGIN, STATS, FUN="-", check.margin=T, ...)

# x is the data
# STATS refers to the summary statistics which you wish to 'sweep out'
# FUN is the function used to carry out the sweep, "-" is the default

Seperti yang Anda lihat, argumennya mirip applymeskipun sweepmembutuhkan satu parameter lagi STATS,.

Perbedaan utama lainnya adalah sweepmengembalikan larik dengan bentuk yang sama seperti larik masukan, sedangkan hasil yang dikembalikan applybergantung pada fungsi yang diteruskan.

sweep sedang beraksi:

# e.g., use 'sweep' to express a given matrix in terms of distance from 
# the respective column mean

# create some data:
M = matrix( 1:12, ncol=3)

# calculate column-wise mean for M
dx = colMeans(M)

# now 'sweep' that summary statistic from M
sweep(M, 2, dx, FUN="-")

     [,1] [,2] [,3]
[1,] -1.5 -1.5 -1.5
[2,] -0.5 -0.5 -0.5
[3,]  0.5  0.5  0.5
[4,]  1.5  1.5  1.5

Singkatnya, yang saya cari adalah satu atau dua contoh kasus penggunaan sweep.

Harap, jangan membaca atau menautkan ke Dokumentasi R, milis, atau sumber R 'utama' - anggap saja saya telah membacanya. Yang saya minati adalah bagaimana programmer / analis R berpengalaman menggunakan sweepkode mereka sendiri.

doug
sumber
2
M-dx tidak mereplikasi hasil Anda. Anda menjawab pertanyaan Anda sendiri.
Yohanes
Satu-satunya penggunaan applyyang bisa saya temukan untuk hasil ini adalah sesuatu seperti t(apply(t(M), 2, "-", dx)), tapi itu cukup buruk.
Ken Williams

Jawaban:

84

sweep()biasanya digunakan saat Anda mengoperasikan matriks demi baris atau kolom, dan input operasi lainnya adalah nilai yang berbeda untuk setiap baris / kolom. Apakah Anda beroperasi menurut baris atau kolom ditentukan oleh MARGIN, seperti untuk apply(). Nilai yang digunakan untuk apa yang saya sebut "input lain" ditentukan oleh STATS. Jadi, untuk setiap baris (atau kolom), Anda akan mengambil nilai dari STATS dan digunakan dalam operasi yang ditentukan oleh FUN.

Misalnya, jika Anda ingin menambahkan 1 ke baris pertama, 2 ke baris ke-2, dll. Dari matriks yang Anda tentukan, Anda akan melakukan:

sweep (M, 1, c(1: 4), "+")

Terus terang saya juga tidak mengerti definisi dalam dokumentasi R, saya hanya belajar dengan melihat contoh.

Daniele Merico
sumber
2
untuk memparafrasekan sedikit: STATStampaknya menjadi label yang buruk untuk variabel ini. Ini adalah input FUNyang digunakan untuk mengubah nilai setiap elemen dalam matriks ( M, dalam contoh ini). STATSdapat berupa konstanta atau daftar / vektor / dll dengan ukuran yang sesuai dengan ukuran yang dipilih MARGIN. Kupikir.
Roland
16

sweep () bisa sangat bagus untuk memanipulasi matriks besar secara sistematis baik kolom demi kolom, atau baris demi baris, seperti yang ditunjukkan di bawah ini:

> print(size)
     Weight Waist Height
[1,]    130    26    140
[2,]    110    24    155
[3,]    118    25    142
[4,]    112    25    175
[5,]    128    26    170

> sweep(size, 2, c(10, 20, 30), "+")
     Weight Waist Height
[1,]    140    46    170
[2,]    120    44    185
[3,]    128    45    172
[4,]    122    45    205
[5,]    138    46    200

Memang, contoh ini sederhana, tetapi mengubah argumen STATS dan FUN, manipulasi lain dimungkinkan.

Brad Horn
sumber
6

Pertanyaan ini agak lama, tetapi karena saya baru saja menghadapi masalah ini, penggunaan sapuan yang khas dapat ditemukan di kode sumber untuk fungsi statistik cov.wt, yang digunakan untuk menghitung matriks kovarians berbobot. Saya melihat kode di R 3.0.1. Di sini sweepdigunakan untuk mengurangi rata-rata kolom sebelum menghitung kovarian. Pada baris 19 kode vektor pemusatan diturunkan:

 center <- if (center) 
        colSums(wt * x)
    else 0

dan pada baris 54 itu disapu dari matriks

x <- sqrt(wt) * sweep(x, 2, center, check.margin = FALSE)

Penulis kode menggunakan nilai default FUN = "-", yang membuat saya bingung untuk sementara waktu.

James King
sumber
3

Salah satu kegunaannya adalah saat Anda menghitung jumlah tertimbang untuk sebuah larik. Dimana rowSumsatau colSumsdapat diasumsikan berarti 'bobot = 1',sweep dapat digunakan sebelumnya untuk memberikan hasil yang berbobot. Ini sangat berguna untuk array dengan> = 3 dimensi.

Ini muncul misalnya saat menghitung matriks kovarians tertimbang sesuai contoh @James King.

Inilah yang lain berdasarkan proyek saat ini:

set.seed(1)
## 2x2x2 array
a1 <- array(as.integer(rnorm(8, 10, 5)), dim=c(2, 2, 2))
## 'element-wise' sum of matrices
## weights = 1
rowSums(a1, dims=2)
## weights
w1 <- c(3, 4)
## a1[, , 1] * 3;  a1[, , 2] * 4
a1 <- sweep(a1, MARGIN=3, STATS=w1, FUN="*")
rowSums(a1, dims=2)
dardisco
sumber
0

Anda dapat menggunakan sweepfungsi untuk menskalakan dan memusatkan data seperti kode berikut. Perhatikan bahwa meansdan sdssewenang-wenang di sini (Anda mungkin memiliki beberapa nilai referensi yang ingin Anda standarisasi datanya berdasarkan nilai tersebut):

df=matrix(sample.int(150, size = 100, replace = FALSE),5,5)

df_means=t(apply(df,2,mean))
df_sds=t(apply(df,2,sd))

df_T=sweep(sweep(df,2,df_means,"-"),2,df_sds,"/")*10+50

Kode ini mengubah skor mentah menjadi skor T (dengan mean = 50 dan sd = 10):

> df
     [,1] [,2] [,3] [,4] [,5]
[1,]  109    8   89   69   15
[2,]   85   13   25  150   26
[3,]   30   79   48    1  125
[4,]   56   74   23  140  100
[5,]  136  110  112   12   43
> df_T
         [,1]     [,2]     [,3]     [,4]     [,5]
[1,] 56.15561 39.03218 57.46965 49.22319 40.28305
[2,] 50.42946 40.15594 41.31905 60.87539 42.56695
[3,] 37.30704 54.98946 47.12317 39.44109 63.12203
[4,] 43.51037 53.86571 40.81435 59.43685 57.93136
[5,] 62.59752 61.95672 63.27377 41.02349 46.09661
Ehsan88
sumber
1
@BenBolker seperti yang saya sebutkan di jawaban, karena saya mungkin ingin menskalakan item sesuai dengan referensi mean dan sd, bukan mean dan sd dari sampel itu sendiri. Ini terjadi saat Anda menangani tes yang diberikan dan distandarisasi dalam sampel besar, dan Anda ingin menstandarkan skor sampel kecil Anda sesuai dengan statistiknya.
Ehsan88