R: คำนวณความสัมพันธ์โดยกลุ่ม


17

ใน R ฉันมีกรอบข้อมูลประกอบไปด้วยฉลากระดับC (ปัจจัย) และสองวัดM1และM2 ฉันจะคำนวณความสัมพันธ์ระหว่างM1และM2ในแต่ละชั้นเรียนได้อย่างไร

โดยหลักการแล้วฉันจะได้กรอบข้อมูลกลับมาหนึ่งแถวสำหรับแต่ละชั้นเรียนและสองคอลัมน์นั่นคือป้ายชื่อชั้นCและสหสัมพันธ์

คำตอบ:


20

แพคเกจ plyr เป็นวิธีที่จะไป

นี่เป็นวิธีง่ายๆ:

xx <- data.frame(group = rep(1:4, 100), a = rnorm(400) , b = rnorm(400) )
head(xx)

require(plyr)
func <- function(xx)
{
return(data.frame(COR = cor(xx$a, xx$b)))
}

ddply(xx, .(group), func)

ผลลัพธ์จะเป็น:

  group         COR
1     1  0.05152923
2     2 -0.15066838
3     3 -0.04717481
4     4  0.07899114

1
(+1) plyrแพ็คเกจดีใช่มั้ย :)
chl

มันใช้งานได้ดี ขอบคุณสำหรับการชี้ให้เห็นแพคเกจ plyr! คุณช่วยอธิบายไวยากรณ์ ". (กลุ่ม)" ได้ไหม
NPE

2
aix - แน่ใจ มันหมายถึง "แบ่งข้อมูลด้วยตัวแปรระหว่าง. () และแต่ละชุดย่อยทำหน้าที่" เพื่อให้มีตัวแปรมากขึ้นคุณควรใช้ไวยากรณ์นี้:. (var1, var2, var3) ซึ่งเป็นเหมือนการตัดข้อมูลของคุณโดยการรวมกันของระดับของ var1, var2 และ var3 และในการตัดแต่ละครั้งเพื่อทำหน้าที่ของคุณ แพ็คเกจนี้ได้รับการดูแลโดย Hadley (เช่นผู้แต่ง ggplot2) ดังนั้นฉันเชื่อว่ามันจะพัฒนาต่อไป
Tal Galili

2
โอ้และ BTW คุณสามารถใช้ plyr กับการคำนวณแบบขนานบนหลายคอร์ (เกือบอัตโนมัติ) ดู: r-statistics.com/2010/09/…
Tal Galili

1
นั่นเป็นคำตอบที่ดี แต่ฉันประหลาดใจที่ไม่มีวิธีแก้ปัญหาแบบในตัวเช่น Cor (x, y, by = z) จะเป็นสิ่งที่ใช้งานง่าย ...
Waldir Leoncio

12

หากคุณมีแนวโน้มที่จะใช้ฟังก์ชั่นในแพ็คเกจพื้นฐานคุณสามารถใช้byฟังก์ชั่นแล้วรวบรวมข้อมูลอีกครั้ง:

xx <- data.frame(group = rep(1:4, 100), a = rnorm(400) , b = rnorm(400) )
head(xx)

# This returns a "by" object
result <- by(xx[,2:3], xx$group, function(x) {cor(x$a, x$b)})

# You get pretty close to what you want if you coerce it into a data frame via a matrix
result.dataframe <- as.data.frame(as.matrix(result))

# Add the group column from the row names
result.dataframe$C <- rownames(result)

1
ดีมากขอบคุณ! ฉันกำลังทดลองกับbyแต่ไม่สามารถหาวิธีแปลงผลลัพธ์ให้เป็นกรอบข้อมูลได้
NPE

9

อีกตัวอย่างหนึ่งที่ใช้แพ็คเกจพื้นฐานและข้อมูลตัวอย่างของ Tal:

DataCov <- do.call( rbind, lapply( split(xx, xx$group),
             function(x) data.frame(group=x$group[1], mCov=cov(x$a, x$b)) ) )

ทางออกที่สง่างาม Joshue คุณคิดว่ามีหลายกรณีที่ทางออกหนึ่งดีกว่าอีกโซลูชันหนึ่ง?
Tal Galili

2
ฉันคิดว่ามันเป็นเรื่องของการตั้งค่า ตัวอย่างของฉันคือสิ่งที่plyrทำ แต่ให้การควบคุมที่ดีกว่าถึงแม้ว่ามันจะไม่สะอาด ความคิดเห็นของฉันจะเปลี่ยนหากวิธีการแก้ปัญหามีโปรไฟล์เวลา / หน่วยความจำดีกว่า ฉันไม่ได้เปรียบเทียบพวกเขา
Joshua Ulrich

สิ่งนี้จะคืนค่าสหสัมพันธ์อย่างไร


0

นี่คือวิธีการที่คล้ายกันซึ่งจะให้ตารางกับค่า n และ p สำหรับแต่ละสหสัมพันธ์เช่นกัน (ปัดเศษเป็นทศนิยม 3 ตำแหน่งเพื่อความสะดวก):

library(Hmisc)
corrByGroup <- function(xx){
  return(data.frame(cbind(correl = round(rcorr(xx$a, xx$b)$r[1,2], digits=3),
                          n = rcorr(xx$a, xx$b)$n[1,2],
                          pvalue = round(rcorr(xx$a, xx$b)$P[1,2], digits=3))))
}

0

นี่คือโซลูชันที่ทันสมัยกว่าโดยใช้ dplyrแพ็คเกจ (ซึ่งยังไม่มีเมื่อถามคำถาม):

สร้างอินพุต:

xx <- data.frame(group = rep(1:4, 100), a = rnorm(400) , b = rnorm(400) )

คำนวณสหสัมพันธ์:

library(dplyr)
xx %>%
  group_by(group) %>%
  summarize(COR=cor(a,b))

ผลลัพธ์:

Source: local data frame [4 x 2]

  group         COR
  (int)       (dbl)
1     1  0.05112400
2     2  0.14203033
3     3 -0.02334135
4     4  0.10626273
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.