2012-08-16 58 views
3

我是R和這個列表的新手。我希望接下來的問題不是太基本或不瞭解。過去幾個小時我一直在檢查檔案,但無濟於事,所以在這裏發佈。部分問題是,當我提及我需要的功能時,我並不完全知道使用的正確術語,這會使搜索變得困難。話雖這麼說,這裏是我需要解決:將數據從一個數據框擴展到另一個數據框中的多行R

我有一個數據幀,看起來像下面這樣:一個項目的多個區域

Subject Item Region RT 
13  102 1 R1 1245 
14  102 4 R1 1677 
15  102 7 R1 1730 
25  103 1 R1 815 
26  103 4 R1 828 
27  103 7 R1 985 
1489  102 1 R2 356 
1490  102 4 R2 510 
1491  102 7 R2 544 
1501  103 1 R2 447 
1502  103 4 R2 486 
1503  103 7 R2 221 
... 

每個受試者的RT(反應時間)。每個主題都會看到多個項目。

我希望計算異常值,然後對它們進行歸一化(儘管我並不真的擔心這個線程中的解決方案)。作爲第一步,我使用了一些簡單的函數來計算的平均值和SD爲每個區域對每個受試者,橫跨物品摺疊(即,(平均所有的RT的該受試者具有在該區域中):

Mean = with(test, aggregate(RT, by = list(Subject,Region),mean, na.rm=TRUE)) 
SD = with(test, aggregate(RT, by = list(Subject,Region),sd, na.rm=TRUE)) 

然後我用cbind並做了一些重命名,以獲得數據都在一個數據幀:

Subject Region  Mean   SD 
1  102 R1 1143.7778 202.25530 
2  102 R2 431.8611 125.84393 
9  103 R1 923.0833 179.51098 
10  103 R2 344.1667 146.51192 
... 

的問題是,我現在需要關聯的所有與每個科目的正確區域的手段也就是說,我會的。喜歡生成看起來像這樣的輸出(請注意,所有主題102區域R1具有相同的平均值和標準差,但不同的RT等):

Subject Item Region RT Mean   SD 
13  102 1 R1 1245 1143.7778 202.25530 
14  102 4 R1 1677 1143.7778 202.25530 
15  102 7 R1 1730 1143.7778 202.25530 
25  103 1 R1 815 923.0833 179.51098 
26  103 4 R1 828 923.0833 179.51098 
27  103 7 R1 985 923.0833 179.51098 
1489  102 1 R2 356 431.8611 125.84393 
1490  102 4 R2 510 431.8611 125.84393 
1491  102 7 R2 544 431.8611 125.84393 
1501  103 1 R2 447 344.1667 146.51192 
1502  103 4 R2 486 344.1667 146.51192 
1503  103 7 R2 221 344.1667 146.51192 

似乎merge和cbind不會做擴展和匹配一個值到另一個值的工作。也許我需要使用融化或某個使用密鑰的功能?

我希望有人可以指向我的相關函數來閱讀,以便我可以自己嘗試,或只是幫助一些代碼。

感謝您的閱讀...

+0

爲什麼你覺得'合併()'是使用的不是在這裏? – A5C1D2H2I1M1N2O1R2T1 2012-08-16 16:50:54

+0

有沒有這樣的事情作爲「太基本的問題」,歡迎來到SO的R部分! ;-) – Rappster 2012-08-17 05:15:19

+0

我懷疑merge()不相關可能是沒有根據的。也許我應該說,我不明白如何使merge()工作來完成我所需要的。我只是找到這個鏈接,這似乎是相關的:http://stackoverflow.com/questions/4227077/merging-two-different-data-frames-in-r – 2012-08-17 09:54:56

回答

3

你可以完成使用ddply功能從plyr包此任務。使用ddplyave功能:

test <- read.table(text=" 
Subject Item Region RT 
13  102 1 R1 1245 
14  102 4 R1 1677 
15  102 7 R1 1730 
25  103 1 R1 815 
26  103 4 R1 828 
27  103 7 R1 985 
1489  102 1 R2 356 
1490  102 4 R2 510 
1491  102 7 R2 544 
1501  103 1 R2 447 
1502  103 4 R2 486 
1503  103 7 R2 221", header=T) 

library(plyr) 
ddply(test, .(Subject, Region), transform, Mean=ave(RT), SD=ave(RT, FUN=sd)) 
    Subject Item Region RT  Mean  SD 
1  102 1  R1 1245 1550.6667 266.03822 
2  102 4  R1 1677 1550.6667 266.03822 
3  102 7  R1 1730 1550.6667 266.03822 
4  102 1  R2 356 470.0000 100.17984 
5  102 4  R2 510 470.0000 100.17984 
6  102 7  R2 544 470.0000 100.17984 
7  103 1  R1 815 876.0000 94.62029 
8  103 4  R1 828 876.0000 94.62029 
9  103 7  R1 985 876.0000 94.62029 
10  103 1  R2 447 384.6667 143.07457 
11  103 4  R2 486 384.6667 143.07457 
12  103 7  R2 221 384.6667 143.07457 

您可以檢查使用aggregate功能,你已經做了的結果。

> with(test, aggregate(RT, by = list(Subject,Region),mean, na.rm=TRUE)) 
    Group.1 Group.2   x 
1  102  R1 1550.6667 
2  103  R1 876.0000 
3  102  R2 470.0000 
4  103  R2 384.6667 
> with(test, aggregate(RT, by = list(Subject,Region),sd, na.rm=TRUE)) 
    Group.1 Group.2   x 
1  102  R1 266.03822 
2  103  R1 94.62029 
3  102  R2 100.17984 
4  103  R2 143.07457 

正如你可以看到無論是平均和SubjectRegion聚合的SD放入你的data.frametest)。

編輯

如果你想處理NA,您可能需要使用下面編輯代碼:

ddply(test, .(Subject, Region), transform, 
     Mean=ave(RT, FUN = function(x) mean(x, na.rm=TRUE)), 
     SD=ave(RT, FUN=function(x) sd(x, na.rm=TRUE))) 
+0

你好Jiber - 謝謝你建議plyr。這似乎與我的完整數據集非常吻合。還有一個問題:對於平均值的計算,現在嵌套在ddply中,它是否默認爲na.rm-TRUE? – 2012-08-17 10:00:25

+0

你好@ user1603288你可以在我的答案中看到編輯,我添加了一種方式,可以讓你處理'NA' – 2012-08-17 21:32:15

+0

@Jiber。謝謝 - 使用ave()對我來說是新的,但你的例子是有道理的。非常感激。 – 2012-08-18 06:56:40

1

這是一種蠻力,但它的工作原理

test <- data.frame(Subject=rep(c(102,103),2,each=3), Item=rep(c(1,4,7),4),Region=rep(c("R1","R2"),each=6), RT= c(1245,1677,1730,815,828,985,356,510,544,447,486,221)) 

Mean = with(test, aggregate(RT, by = list(Subject,Region),mean, na.rm=TRUE)) 
SD = with(test, aggregate(RT, by = list(Subject,Region),sd, na.rm=TRUE)) 

aa <- data.frame(test, Mean=0, SD=0) 

for (i in 1:nrow(aa)) { 
    for(j in 1:nrow(Mean)){ 
    if (aa$Subject[i]==Mean$Group.1[j] & aa$Region[i]==Mean$Group.2[j]) aa$Mean[i] <- Mean$x[j] 
    if (aa$Subject[i]==SD$Group.1[j] & aa$Region[i]==SD$Group.2[j]) aa$SD[i] <- SD$x[j] 
    } 
} 
+0

感謝您的建議擦。其他方法可能更容易,因爲我擁有比我上面指出的更多的主題和項目。我希望能夠建立一個更一般的例程,以便將它應用於大量數據。但我仍然會仔細研究,以便我能夠更多地學習如何思考。 – 2012-08-17 10:51:47

2

你有99%完成了你的工作。你需要做的唯一的事情是「漂亮」你的aggregate()輸出,所以它的工作更禮貌merge()。請注意,在下文中,您將指定輸出列名稱,以便可以輕鬆合併它們。

然後,我們使用Reduce()遞歸合併。

Mean = with(test, aggregate(list(mean = RT), 
          by = list(Subject = Subject, Region = Region), 
          mean, na.rm=TRUE)) 
SD = with(test, aggregate(list(sd = RT), 
          by = list(Subject = Subject, Region = Region), 
          sd, na.rm=TRUE)) 
Reduce(function(x, y) merge(x, y), list(test, Mean, SD)) 
# Subject Region Item RT  mean  sd 
# 1  102  R1 1 1245 1550.6667 266.03822 
# 2  102  R1 4 1677 1550.6667 266.03822 
# 3  102  R1 7 1730 1550.6667 266.03822 
# 4  102  R2 1 356 470.0000 100.17984 
# 5  102  R2 4 510 470.0000 100.17984 
# 6  102  R2 7 544 470.0000 100.17984 
# 7  103  R1 1 815 876.0000 94.62029 
# 8  103  R1 4 828 876.0000 94.62029 
# 9  103  R1 7 985 876.0000 94.62029 
# 10  103  R2 1 447 384.6667 143.07457 
# 11  103  R2 4 486 384.6667 143.07457 
# 12  103  R2 7 221 384.6667 143.07457 
# merge(merge(test, Mean), SD) 
+0

嗨mrdwab。感謝您的建議,並試圖與我迄今所做的一切合作。這可能很簡單,但我不太明白你的代碼的這一部分發生了什麼:(list(mean = RT)。你可能的意思是(list(mean,RT))其餘的,似乎相當清楚,至少目前爲止 – 2012-08-17 10:48:13

+0

@ user1603288,'list(mean = RT)'意味着要創建一個名爲'mean'的列,如果我將它命名爲「Mean」,可能會更不困惑,因爲有函數命名爲'mean()'。如果你沒有指定列名(在列表中,就像我在這裏做的那樣),結果看起來就像Jilber的'aggregate()'示例,列名爲'Group.1',因爲我建議你「聚合」你的'aggregate()'輸出。 – A5C1D2H2I1M1N2O1R2T1 2012-08-17 10:53:44

+0

@mrwab。我確實知道你在聚合函數中指定了名字(如果我可以說它是類似的),這與主題和區域列表組件很相似,但我仍然在努力理解爲什麼要將RT指定爲「mean」(或「Mean」,正如你所建議的)。聯合國將此語法定義爲「在RT中按列測試操作平均函數(按主題和區域),然後爲其指定名稱」mean「?這當然是它似乎在做什麼,但我想確保我得到這裏到底發生了什麼。謝謝! – 2012-08-17 11:26:30

3

這是可以做到USNG sqldf

df1<-read.table(header=T,text="Subject Item Region RT 
13  102 1 R1 1245 
14  102 4 R1 1677 
15  102 7 R1 1730 
25  103 1 R1 815 
26  103 4 R1 828 
27  103 7 R1 985 
1489  102 1 R2 356 
1490  102 4 R2 510 
1491  102 7 R2 544 
1501  103 1 R2 447 
1502  103 4 R2 486 
1503  103 7 R2 221") 

df2<-read.table(header=T,text="Subject Region  Mean   SD 
1  102 R1 1143.7778 202.25530 
2  102 R2 431.8611 125.84393 
9  103 R1 923.0833 179.51098 
10  103 R2 344.1667 146.51192") 

library(sqldf) 
sqldf("SELECT df1.*,df2.Mean,df2.SD from df1,df2 
     WHERE df1.Region=df2.Region 
     GROUP BY df1.Region,df1.Subject,df1.Item") 

# Subject Item Region RT  Mean  SD 
#1  102 1  R1 1245 1143.7778 202.2553 
#2  102 4  R1 1677 1143.7778 202.2553 
#3  102 7  R1 1730 1143.7778 202.2553 
#4  103 1  R1 815 1143.7778 202.2553 
#5  103 4  R1 828 1143.7778 202.2553 
#6  103 7  R1 985 1143.7778 202.2553 
#7  102 1  R2 356 431.8611 125.8439 
#8  102 4  R2 510 431.8611 125.8439 
#9  102 7  R2 544 431.8611 125.8439 
#10  103 1  R2 447 431.8611 125.8439 
#11  103 4  R2 486 431.8611 125.8439 
#12  103 7  R2 221 431.8611 125.8439 

它是由地區排序,然後受試者項目

+0

這看起來也不錯,謝謝! – 2012-08-17 10:37:43

相關問題