plyr package เขียนฟังก์ชันเดียวกันบนหลายคอลัมน์

ฉันต้องการเขียนฟังก์ชันเดียวกันลงในหลายคอลัมน์โดยใช้ฟังก์ชัน ddply แต่ฉันพยายามเขียนเป็นบรรทัดเดียวต่อไป ต้องการดูว่ามีวิธีที่ดีกว่าในการทำเช่นนี้หรือไม่

ต่อไปนี้เป็นข้อมูลเวอร์ชันง่ายๆ:

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

และฉันต้องการหาผลรวมของคอลัมน์ A_MEAN_WEIGHT และ B_MEAN_WEIGHT โดยทำสิ่งนี้:

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

แต่ในข้อมูลปัจจุบันของฉันฉันมีมากกว่า 8 "*_MEAN_WEIGHT" และฉันเบื่อที่จะเขียนมัน 8 ครั้งเช่น

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))

มีวิธีเขียนที่ดีกว่านี้ไหม? ขอขอบคุณสำหรับความช่วยเหลือของคุณ!!


person linp    schedule 18.04.2013    source แหล่งที่มา


คำตอบ (2)


แนวทาง plyr เป็นศูนย์กลางคือการใช้ 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

คุณสามารถส่งชื่อคอลัมน์เป็นอาร์กิวเมนต์ .col ได้ หากคุณต้องการเพียงเซ็ตย่อย

คุณยังสามารถใช้ numcolwise หรือ catcolwise เพื่อดำเนินการกับคอลัมน์ตัวเลขหรือหมวดหมู่เท่านั้น

โปรดทราบว่าคุณสามารถใช้ sapply แทนการใช้งานขั้นพื้นฐานที่สุดของ colwise

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

วิธีการ data.table สำนวนคือการใช้ 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
ขอบคุณ @mnel! อีกหนึ่งคำถาม ดูเหมือนว่าฉันจะเขียนแบบนี้ไม่ได้ ddply(data, .(TYPE),colwise(sum,.(A_MEAN_WEIGHT)),colwise(sqrt,.(B_MEAN_WEIGHT))) ดังนั้นถ้าฉัน ต้องการสองฟังก์ชันที่แตกต่างกันบนหลายคอลัมน์ ฉันต้องเขียนมันสองครั้งหรือไม่ - person linp; 19.04.2013

ลองสิ่งนี้:

ddply(data, .(TYPE), colSums)

นี่คือสิ่งที่เทียบเท่า (ช้ากว่า) ข้างต้น ซึ่งสามารถปรับแต่งเพื่อใส่ฟังก์ชันใดๆ แทนการรวม:

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

และหากคุณต้องการคงคอลัมน์ .(TYPE) ไว้ ให้ทำดังนี้:

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

ยังดีกว่า ให้ใช้ data.table แทน 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
ทำงานได้อย่างสมบูรณ์แบบ! ขอบคุณ @เอ็ดดี้!! - person linp; 18.04.2013
comment
อืม...คำถามติดตามผล จะเป็นอย่างไรถ้าฉันมี 16 คอลัมน์ และฉันต้องการหาผลรวมของ 8 คอลัมน์นั้น และ sqrt(sum) ของอีก 8 คอลัมน์ที่เหลือ.... - person linp; 18.04.2013
comment
คุณสามารถเช่น รันคำสั่งด้านบนสองครั้ง - หนึ่งครั้งกับแต่ละฟังก์ชันและกรองตามคอลัมน์ที่คุณต้องการ (เช่น โดยทำ names(x) %in% c("column_a", "column_b", ...) ใน apply หรือตามหมายเลขคอลัมน์หรืออะไรก็ตามที่เหมาะสมสำหรับข้อมูลของคุณ) จากนั้น cbind ผลลัพธ์ - person eddi; 18.04.2013
comment
คุณสามารถดำเนินธุรกิจ dt[, ...] สองครั้งโดยใช้ค่าที่แตกต่างกันสำหรับ .SDcols ในแต่ละครั้ง จากนั้นจึง cbind ผลลัพธ์ หากคุณเข้าใจความหมายของฉัน ... - person Steve Lianoglou; 19.04.2013
comment
อย่าใช้ colSums กับ data.table หรือ apply ทั้งสองอย่างจะแปลงเป็นเมทริกซ์ภายใน ดังนั้นจึงไม่มีประสิทธิภาพ - person mnel; 19.04.2013
comment
อย่าใช้ colSums หรือนำไปใช้กับ data.frame เช่นกัน - person mnel; 19.04.2013
comment
@mnel ในการทดสอบของฉัน dt[, colSums(.SD)] เร็วกว่า dt[, lapply(.SD, sum)] ประมาณ 10% ดังนั้นฉันไม่คิดว่าความคิดเห็นของคุณถูกต้อง - person eddi; 19.04.2013
comment
มันอาจไม่กัดเมื่อคุณจัดการกับชุดข้อมูลขนาดเล็ก แต่ดูที่ซอร์สโค้ดของแต่ละฟังก์ชัน และทำการเปรียบเทียบข้อมูลขนาดใหญ่ - person mnel; 20.04.2013
comment
ยุติธรรมเพียงพอ ดำเนินการตรวจสอบมากขึ้น แน่นอนว่า colSums จะเร็วกว่ากับข้อมูลที่เล็กลง แต่จะช้าลงเมื่อมีข้อมูลที่ใหญ่กว่า - person eddi; 20.04.2013