R: การต่อท้ายกรอบข้อมูลใน for loop

ดังนั้นฉันจึงมีลูปนี้ และมันเขียนไฟล์ csv หลายไฟล์ โดยแต่ละไฟล์ถูกต่อท้ายจากผลลัพธ์ของการรัน ดังที่คุณเห็นด้านล่าง การวนซ้ำนี้เรียกใช้ฟังก์ชันทางสถิติ (zScore) ในแต่ละแถวของชุดย่อยจาก gex ต่อ mxy จากนั้นเผยแพร่ผลลัพธ์สำหรับแต่ละแถว จากนั้นย้ายไปยังชุดย่อยถัดไปของ gex

คำถามของฉันคือ แทนที่จะเขียนผลลัพธ์ต่อท้ายเป็นไฟล์ csv มีวิธีที่ฉันสามารถสร้าง dataframe ภายในลูปที่มีลักษณะเหมือนกันได้หรือไม่

ขอบคุณสำหรับความช่วยเหลือของคุณ

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 แหล่งที่มา
comment
ประกาศ dataframe นอกลูป จากนั้นใช้ rbind หรือ cbind เพื่อเพิ่มแถวหรือคอลัมน์ในการวนซ้ำแต่ละครั้งของลูป   -  person Sam Firke    schedule 05.02.2015
comment
สวัสดี @SamFirke ขอบคุณสำหรับคำติชม - ฉันจะประกาศ dataframe นอกลูปในขณะที่ยังคงใช้การวนซ้ำแต่ละครั้งได้อย่างไร   -  person Henri Wathieu    schedule 05.02.2015
comment
@SamFirke โดยทั่วไปแล้วสิ่งนี้ค่อนข้างไม่มีประสิทธิภาพใน R - ลองดู Circle 2 ของ The R นรก.   -  person josliber♦    schedule 05.02.2015
comment
ขอบคุณสำหรับลิงก์ @josilber ฉันรู้ว่าควรหลีกเลี่ยง for-loops ใน R โดยทั่วไป แต่ไม่ทราบถึงผลกระทบของหน่วยความจำ @HenriW ดูวิธีแก้ปัญหาของ josilber คุณสามารถสร้าง data frame ในตอนแรกเหมือนที่เขาทำ จากนั้นจึงต่อท้ายการวนซ้ำแต่ละครั้งโดยใช้การเรียก rbind - แต่วิธีแก้ปัญหาของเขาด้วย lapply นั้นดีกว่าในขณะที่เขาอธิบาย   -  person Sam Firke    schedule 05.02.2015


คำตอบ (1)


ในโค้ดที่คุณโพสต์ คุณมีไฟล์ csv หนึ่งไฟล์สำหรับแต่ละองค์ประกอบของ listx และคุณกำลังเขียนบรรทัดจำนวนหนึ่งทีละบรรทัดลงในแต่ละไฟล์เหล่านี้ คุณสามารถสร้างกรอบข้อมูลสำหรับแต่ละองค์ประกอบของ listx และเขียนแต่ละองค์ประกอบด้วยการเรียก 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

ตอนนี้คุณสามารถส่งออกเฟรมข้อมูลแบบเต็มสำหรับแต่ละคอลัมน์โดยใช้ write.table

การรวมกรอบข้อมูลทั้งหมดเข้าด้วยกันในการเรียก rbind เพียงครั้งเดียวจะมีประสิทธิภาพมากกว่าการเรียก rbind ในการวนซ้ำแต่ละครั้ง ดูวงกลมที่ 2 ของ The R Inferno สำหรับรายละเอียดเพิ่มเติม

person josliber♦    schedule 05.02.2015
comment
ฉันเข้าใจการเปลี่ยนแปลงของคุณในแง่ของประสิทธิภาพ แต่ไม่ได้รวบรวมสิ่งต่าง ๆ อย่างที่ฉันต้องการ ปัญหาของฉันคือ อย่างที่คุณเห็นใน OP ฉันเขียน geneexptest ทุกครั้งที่สร้างมันขึ้นมา กุญแจสำคัญอยู่ที่ตัวเลือก append=(i > 1) ใน write.table ฉันต้องการทำสิ่งเดียวกัน แต่จัดการ geneexptest (ในรูปแบบต่อท้าย...) ลงใน dataframe อื่นแล้วเขียนลงใน csv (แล้วเลื่อนไปรอบต่อไป ฯลฯ) มีความคิดใดบ้างที่ฉันสามารถทำได้? - person Henri Wathieu; 09.02.2015
comment
@HenriW รหัสนี้จะผนวกทุก ๆ geneexptest ลงในกรอบข้อมูลเดียว คุณสามารถเขียนลงในไฟล์ที่ลงท้ายด้วย write.table น่าเสียดายที่โพสต์ต้นฉบับของคุณไม่สามารถทำซ้ำได้ (ฉันไม่สามารถเรียกใช้โค้ดของคุณตามที่โพสต์ได้) ดังนั้นจึงเป็นเรื่องยากที่จะทำซ้ำฟังก์ชันการทำงานทั้งหมด ฉันขอแนะนำให้คุณอัปเดตคำถามของคุณเพื่อให้สามารถทำซ้ำได้หากคุณต้องการความช่วยเหลือเพิ่มเติม - person josliber♦; 10.02.2015
comment
ฉันได้แนบบางสิ่งเพื่อสร้างข้อมูลที่เกี่ยวข้อง โปรดแจ้งให้เราทราบว่าคุณคิดอย่างไร ดังนั้น ฉันต้องการให้มันมีฟังก์ชันการทำงานแบบเดียวกัน แต่มีความเป็นไปได้ที่จะรวมการจัดการเพิ่มเติมบางอย่างก่อนที่แต่ละรอบจะถูกส่งออกใน write.table นั่นเป็นเหตุผลที่ฉันถามเกี่ยวกับการต่อท้าย dataframes ภายใน for loop - person Henri Wathieu; 13.02.2015
comment
@HenriW ฉันได้อัปเดตโค้ดตามคำถามที่อัปเดตของคุณ นี่เป็นการเน้นย้ำถึงความสำคัญของการโพสต์ตัวอย่างปัญหาของคุณที่ทำซ้ำได้ในคำถามของคุณใน SO - person josliber♦; 14.02.2015
comment
มีประโยชน์มาก!! สิ่งสุดท้าย: ฉันกำลังพยายามปรับเปลี่ยนสิ่งต่าง ๆ ภายในลูป ซึ่งตอนนี้แสดงเป็นส่วนเสริมของโพสต์ต้นฉบับ คุณจะเห็นได้ว่า data.frame(...) ตัวสุดท้ายพยายามสร้าง geneexptotal ไม่ใช่ geneexptest เหมือนเมื่อก่อน อย่างไรก็ตาม สิ่งที่กำลังผลิตอยู่จริงๆ คือ geneexptestapp มีเหตุผลอะไรที่จะหยุดสั้น ณ จุดนั้นหรือไม่? - person Henri Wathieu; 16.02.2015
comment
@HenriW โดยทั่วไปวิธีที่ดีที่สุดคือถามคำถามใหม่หากคุณมีปัญหาการเขียนโปรแกรมใหม่แทนที่จะแก้ไขคำถามเก่า - สิ่งนี้จะทำให้แน่ใจว่าทั้งชุมชนเห็นปัญหาใหม่ของคุณ หากคำตอบของฉันสามารถตอบคำถามเดิมของคุณได้ ฉันขอแนะนำให้คุณยอมรับและถามคำถามใหม่เกี่ยวกับปัญหาใหม่ของคุณ - person josliber♦; 16.02.2015