R: Menambahkan ke bingkai data dalam perulangan for

Jadi saya memiliki loop ini, dan ia menulis beberapa file csv, dengan masing-masing file telah ditambahkan dari hasil proses. Seperti yang Anda lihat di bawah, loop khusus ini menjalankan fungsi statistik (zScore) di setiap baris subset dari gex terhadap mxy, lalu menerbitkan hasil untuk setiap baris, lalu berpindah ke subset gex berikutnya.

Pertanyaan saya adalah, alih-alih menulis hasil yang ditambahkan sebagai file csv, adakah cara agar saya bisa membuat kerangka data di dalam loop yang terlihat sama?

Terima kasih atas bantuan baik Anda.

gex <- data.frame("sample" =  c("BIX","HEF","TUR","ZOP","VAG"), 
                  "TCGA-F4-6703-01" = runif(5, -1, 1),
                  "TCGA-DM-A28E-01" = runif(5, -1, 1),
                  "TCGA-AY-6197-01" = runif(5, -1, 1),
                  "TCGA-A6-5657-01" = runif(5, -1, 1))
colnames(gex) <- gsub("[.]", "_",colnames(gex))

listx <- c("TCGA_DM_A28E_01","TCGA_A6_5657_01")

mxy <- data.frame("TCGA-AD-6963-01" = runif(5, -1, 1),
                  "TCGA-AA-3663-11" = runif(5, -1, 1),
                  "TCGA-AD-6901-01" = runif(5, -1, 1),
                  "TCGA-AZ-2511-01" = runif(5, -1, 1),
                  "TCGA-A6-A567-01" = runif(5, -1, 1)) 

colnames(mxy) <- gsub("[.]", "_",colnames(mxy))

zScore <- function(x,y)((as.numeric(x) - as.numeric(rowMeans(y,na.rm=T)))/as.numeric(sd(y,na.rm=T)))

   for(i in seq(nrow(mxy))){
      for(colName in listx){
        zvalues <- zScore(gex[i,colName],
                          mxy[i,])
        geneexptest <- data.frame(gex$sample[i], zvalues, row.names = NULL, 
                                  stringsAsFactors = TRUE)
        write.table(geneexptest, file = paste0(colName, "mxyinput", ".csv"),
                    row.names=FALSE, col.names=FALSE,  quote=F,
                    sep = ",", dec = ".", append=(i > 1))
      }
    }

person Henri Wathieu    schedule 05.02.2015    source sumber
comment
Deklarasikan kerangka data di luar loop, lalu gunakan rbind atau cbind untuk menambahkan baris atau kolom di setiap iterasi loop?   -  person Sam Firke    schedule 05.02.2015
comment
Hai @SamFirke, terima kasih atas masukannya - bagaimana cara mendeklarasikan kerangka data di luar loop sambil tetap menggunakan setiap iterasi loop?   -  person Henri Wathieu    schedule 05.02.2015
comment
@SamFirke ini umumnya tidak efisien di R -- lihat Lingkaran 2 dari R Neraka.   -  person josliber♦    schedule 05.02.2015
comment
Terima kasih untuk tautannya @josilber, saya tahu untuk menghindari for-loop di R secara umum tetapi tidak menyadari implikasi memori. @HenriW, lihat solusi josilber; Anda dapat membuat bingkai data pada awalnya seperti yang dia lakukan, lalu menambahkannya pada setiap iterasi loop menggunakan panggilan rbind - tetapi solusinya dengan lapply lebih baik seperti yang dia jelaskan.   -  person Sam Firke    schedule 05.02.2015


Jawaban (1)


Dalam kode yang Anda posting, Anda memiliki satu file csv untuk setiap elemen listx, dan Anda menulis sejumlah baris satu per satu ke dalam setiap file ini. Sebagai gantinya, Anda dapat membuat bingkai data untuk setiap elemen listx dan menulis setiap elemen dengan satu panggilan ke write.table.

dfs <- lapply(listx, function(colName) {
  do.call(rbind, lapply(seq(nrow(mxy)), function(i) {
    zvalues <- zScore(gex[i,colName], mxy[i,])
    data.frame(gex$sample[i], zvalues, row.names = NULL, stringsAsFactors = TRUE)
  }))
})
dfs
# [[1]]
#   gex.sample.i.    zvalues
# 1           BIX  1.1105593
# 2           HEF  0.5451948
# 3           TUR -1.4060388
# 4           ZOP -1.4218218
# 5           VAG  0.2780513
# 
# [[2]]
#   gex.sample.i.   zvalues
# 1           BIX 2.0607386
# 2           HEF 1.6703912
# 3           TUR 1.3249181
# 4           ZOP 0.8865058
# 5           VAG 1.5289732

Sekarang Anda dapat menampilkan bingkai data lengkap untuk setiap kolom menggunakan write.table.

Menggabungkan semua frame data bersama-sama dalam satu panggilan ke rbind akan jauh lebih efisien daripada memanggil rbind pada setiap iterasi loop; lihat Lingkaran 2 dari The R Inferno untuk detail lebih lanjut.

person josliber♦    schedule 05.02.2015
comment
Saya memahami perubahan Anda dalam hal efisiensi, tetapi perubahan tersebut tidak berjalan sesuai keinginan saya. Masalah saya adalah, seperti yang Anda lihat di OP, saya menulis geneexptest setiap kali saya membuatnya. Kuncinya ada opsi append=(i > 1) di write.table. Saya ingin melakukan hal yang persis sama, tetapi memanipulasi geneexptest (dalam bentuk tambahannya...) ke dalam kerangka data lain dan LALU menuliskannya ke csv. (Kemudian lanjutkan ke babak berikutnya, dll). Adakah yang tahu bagaimana saya bisa melakukan itu? - person Henri Wathieu; 09.02.2015
comment
@HenriW kode ini menambahkan setiap geneexptest ke dalam satu bingkai data. Anda bisa menuliskannya ke file di akhir dengan write.table. Sayangnya postingan asli Anda tidak dapat direproduksi (saya tidak dapat menjalankan kode Anda seperti yang diposting) sehingga sulit untuk mereplikasi fungsinya secara tepat. Saya mendorong Anda untuk memperbarui pertanyaan Anda agar dapat direproduksi jika Anda memerlukan bantuan lebih lanjut. - person josliber♦; 10.02.2015
comment
Saya telah melampirkan beberapa hal untuk membangun masukan yang relevan - beri tahu saya pendapat Anda. Jadi, saya ingin ini memiliki fungsi yang sama, tetapi dengan kemungkinan menyertakan beberapa manipulasi tambahan SEBELUM setiap putaran dikeluarkan di write.table. Itu sebabnya saya bertanya tentang menambahkan kerangka data dalam loop for. - person Henri Wathieu; 13.02.2015
comment
@HenriW Saya telah memperbarui kode saya berdasarkan pertanyaan Anda yang diperbarui. Ini benar-benar menyoroti pentingnya memposting contoh masalah Anda yang dapat direproduksi dalam pertanyaan Anda di SO. - person josliber♦; 14.02.2015
comment
Sangat membantu!! Jadi, satu hal lagi: Saya mencoba memodulasi hal-hal di dalam loop, yang sekarang ditampilkan dalam suplemen pada postingan asli. Di sana, Anda dapat melihat bahwa data.frame(...) terakhir mencoba menghasilkan geneexptotal, bukan geneexptest seperti sebelumnya. Namun yang dihasilkan justru geneexptestapp. Apakah ada alasan mengapa hal itu berhenti pada saat itu? - person Henri Wathieu; 16.02.2015
comment
@HenriW secara umum yang terbaik adalah mengajukan pertanyaan baru jika Anda memiliki masalah pemrograman baru daripada mengedit yang lama -- ini memastikan seluruh komunitas melihat masalah baru Anda. Jika jawaban saya telah menyelesaikan pertanyaan awal Anda, saya akan mendorong Anda untuk menerimanya dan mengajukan pertanyaan baru dengan masalah baru Anda. - person josliber♦; 16.02.2015