在R中将数据从一个数据帧扩展到另一个数据帧中的多个行

时间:2012-08-16 13:55:12

标签: r dataframe

我是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(反应时间)。每个主题都会看到多个项目。

我希望计算异常值然后将它们标准化(尽管我不会真的担心这个问题中的解决方案)。作为第一步,我使用一些简单的函数来计算每个主题的每个区域的平均值和标准差,折叠项目(即(主题在该区域中的所有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  
...  

问题在于我现在需要将所有方法与每个主题的正确区域相关联。也就是说,我想生成看起来像这样的输出(请注意,所有Subject 102 Region R1具有相同的均值和SD,但不同的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不会完成将一个值扩展和匹配到另一个值的工作。也许我需要使用融化或某些使用密钥的功能?

我希望有人能指出我的相关功能让我阅读,以便我可以自己尝试,或只是帮助一些代码。

感谢阅读...

4 个答案:

答案 0 :(得分: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)))

答案 1 :(得分:3)

这可以通过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

它按地区,主题然后项目

排序

答案 2 :(得分:2)

99%的人完成了你的工作。你唯一需要做的就是&#34;漂亮的&#34;您的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)

答案 3 :(得分: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]
  }
}