paket plyr menulis fungsi yang sama pada beberapa kolom

Saya ingin menulis fungsi yang sama ke beberapa kolom menggunakan fungsi ddply, tetapi saya mencoba tetap menuliskannya dalam satu baris, ingin melihat apakah ada cara yang lebih baik untuk melakukan ini?

Berikut versi sederhana datanya:

data<-data.frame(TYPE=as.integer(runif(20,1,3)),A_MEAN_WEIGHT=runif(20,1,100),B_MEAN_WEIGHT=runif(20,1,10))

dan saya ingin mengetahui jumlah kolom A_MEAN_WEIGHT dan B_MEAN_WEIGHT dengan melakukan ini:

ddply(data,.(TYPE),summarise,MEAN_A=sum(A_MEAN_WEIGHT),MEAN_B=sum(B_MEAN_WEIGHT))

tetapi dalam data saya saat ini saya memiliki lebih dari 8 "*_MEAN_WEIGHT", dan saya bosan menulisnya 8 kali seperti

ddply(data,.(TYPE),summarise,MEAN_A=sum(A_MEAN_WEIGHT),MEAN_B=sum(B_MEAN_WEIGHT),MEAN_C=sum(C_MEAN_WEIGHT),MEAN_D=sum(D_MEAN_WEIGHT),MEAN_E=sum(E_MEAN_WEIGHT),MEAN_F=sum(F_MEAN_WEIGHT),MEAN_G=sum(G_MEAN_WEIGHT),MEAN_H=sum(H_MEAN_WEIGHT))

Apakah ada cara yang lebih baik untuk menulis ini? Terima kasih untuk bantuannya!!


person linp    schedule 18.04.2013    source sumber


Jawaban (2)


Pendekatan yang berpusat pada plyr adalah dengan menggunakan colwise

eg

 ddply(data, .(TYPE), colwise(sum))
  TYPE A_MEAN_WEIGHT B_MEAN_WEIGHT
1    1      319.8977      60.80317
2    2      621.6745      37.05863

Anda dapat meneruskan nama kolom sebagai argumen .col jika Anda hanya menginginkan sebagian saja

Anda juga dapat menggunakan numcolwise atau catcolwise untuk bertindak pada kolom numerik atau kategorikal saja.

perhatikan bahwa Anda dapat menggunakan sapply sebagai pengganti penggunaan paling dasar colwise

ddply(data, .(TYPE), sapply, FUN = 'mean') 

Pendekatan data.table idiomatis adalah dengan menggunakan lapply(.SD, fun)

eg

dt <- data.table(data)
dt[,lapply(.SD, sum) ,by = TYPE]
   TYPE A_MEAN_WEIGHT B_MEAN_WEIGHT
1:    2      621.6745      37.05863
2:    1      319.8977      60.80317
person mnel    schedule 18.04.2013
comment
Terima kasih @mnel! hanya satu pertanyaan lagi, sepertinya saya tidak bisa menulisnya seperti ini ddply(data, .(TYPE),colwise(sum,.(A_MEAN_WEIGHT)),colwise(sqrt,.(B_MEAN_WEIGHT))), jadi jika saya ingin dua fungsi berbeda pada beberapa kolom, saya perlu menulisnya dua kali? - person linp; 19.04.2013

Coba ini:

ddply(data, .(TYPE), colSums)

Berikut ini setara (lebih lambat) dari yang di atas, yang dapat diubah untuk menempatkan fungsi apa pun alih-alih menjumlahkan:

ddply(data, .(TYPE), function(x) {apply(x, 2, sum)})

Dan jika Anda ingin mempertahankan kolom .(TYPE), lakukan hal seperti ini:

ddply(data, .(TYPE), function(x) {apply(x[,names(x) != "TYPE"], 2, sum)})

Lebih baik lagi, gunakan data.table daripada plyr:

library(data.table)
dt = data.table(data)

# just sums
dt[, data.table(t(colSums(.SD))), by = TYPE]

# sum for "A" and "B", and sqrt(sum) for "C" and "D"
# note: you will have to call setnames() to fix the column names after
dt[, data.table(t(colSums(.SD[, c("A_MEAN_WEIGHT", "B_MEAN_WEIGHT"), with = F])),
                t(apply(.SD[, c("C_MEAN_WEIGHT", "D_MEAN_WEIGHT"), with = F],
                        2, function(x) sqrt(sum(x))))),
     by = TYPE]
person eddi    schedule 18.04.2013
comment
Bekerja dengan sempurna! Terima kasih @eddi!! - person linp; 18.04.2013
comment
Emm...pertanyaan lanjutan, bagaimana jika saya memiliki 16 kolom, dan saya ingin menjumlahkan 8 kolom, dan sqrt(jumlah) dari 8 kolom lainnya.... - person linp; 18.04.2013
comment
Anda bisa, misalnya. jalankan perintah di atas dua kali - sekali dengan setiap fungsi dan memfilter berdasarkan kolom yang Anda inginkan (misalnya dengan melakukan names(x) %in% c("column_a", "column_b", ...) di apply atau berdasarkan nomor kolom atau apa pun yang sesuai untuk data Anda) dan kemudian cbind hasilnya - person eddi; 18.04.2013
comment
Sebagai alternatif, Anda dapat menjalankan bisnis dt[, ...] dua kali menggunakan nilai yang berbeda untuk .SDcols setiap kali, lalu cbind hasilnya, jika Anda mengerti maksud saya ... - person Steve Lianoglou; 19.04.2013
comment
Jangan gunakan colSums pada data.table atau apply -- keduanya akan dikonversi menjadi matriks secara internal, dan karenanya tidak efisien. - person mnel; 19.04.2013
comment
Jangan gunakan colSums atau terapkan pada data.frame juga. - person mnel; 19.04.2013
comment
@mnel dalam pengujian saya dt[, colSums(.SD)] sekitar 10% lebih cepat dari dt[, lapply(.SD, sum)], jadi menurut saya komentar Anda tidak benar - person eddi; 19.04.2013
comment
Ini mungkin tidak berlaku ketika Anda berurusan dengan kumpulan data kecil. Namun lihat kode sumber untuk setiap fungsi, dan lakukan benchmarking dengan data yang besar. - person mnel; 20.04.2013
comment
cukup adil, menjalankan lebih banyak pemeriksaan, memang colSums lebih cepat pada data yang lebih kecil, namun menjadi lebih lambat dengan data yang lebih besar - person eddi; 20.04.2013