如何通过分类变量过滤R中的data.frame?

时间:2011-02-19 18:17:09

标签: r statistics dataframe

刚刚学习R.

如果R中的data.frame有两列,一个数字和一个分类,如何提取data.frame的一部分用于使用?

str(ex0331)
'data.frame':   36 obs. of  2 variables:
$ Iron      : num  0.71 1.66 2.01 2.16 2.42 ...
$ Supplement: Factor w/ 2 levels "Fe3","Fe4": 1 1 1 1 1 1 1 1 1 1 ...

基本上,我需要能够分别对这两个因素进行操作;即我需要能够按Supplement类型(Fe3Fe4)单独确定铁保留率的长度/平均值/标准差/秒等。

实现这一目标的最简单方法是什么?

我知道by()命令。例如,以下内容得到了我需要的一些内容:

by(ex0331, ex0331$Supplement, summary)
ex0331$Supplement: Fe3
     Iron       Supplement
Min.   :0.710   Fe3:18    
1st Qu.:2.420   Fe4: 0    
Median :3.475             
Mean   :3.699             
3rd Qu.:4.472             
Max.   :8.240             
------------------------------------------------------------ 
ex0331$Supplement: Fe4
     Iron        Supplement
Min.   : 2.200   Fe3: 0    
1st Qu.: 3.892   Fe4:18    
Median : 5.750             
Mean   : 5.937             
3rd Qu.: 6.970             
Max.   :12.450      

但我需要更多的灵活性。例如,我需要应用axis命令,或按组应用log()个函数。我确信有一个简单的方法可以做到这一点;我只是没有看到它。我见过的所有data.frame操作文档都是数字而非分类变量。

2 个答案:

答案 0 :(得分:3)

我建议使用ddply包中的plyr功能,详细的文档在线:

> require(plyr)
> ddply( ex0331, .(Supplement), summarise, 
         mean = mean(Iron), 
         sd = sd(Iron), 
         len = length(Iron))

  Supplement       mean        sd len
1        Fe3 -0.3749169 0.2827360   4
2        Fe4  0.1953116 0.7128129   6

<强>更新即可。 要添加LogIron列,其中每个条目都是log()值的Iron,您只需使用transform

> transform(ex0331, LogIron = log(Iron))

         Iron Supplement     LogIron
1  0.07185141        Fe3 -2.63315498
2  1.10367297        Fe3  0.09864368
3  0.48592428        Fe3 -0.72170246
4  0.20286918        Fe3 -1.59519393
5  0.80830682        Fe4 -0.21281357

或者,要创建一个摘要,即“每个补充的日志铁值的平均值”,您可以这样做:

> ddply( ex0331, .(Supplement), summarise, meanLog = mean(log(Iron)))
  Supplement    meanLog
1        Fe3 -1.0062304
2        Fe4  0.2791507

答案 1 :(得分:3)

您可以通过索引或使用subset来获取数据的子集:

ex0331 <- data.frame( iron=rnorm(36), supplement=c("Fe3","Fe4"))

subset(ex0331, supplement=="Fe3")
subset(ex0331, supplement=="Fe4")

ex0331[ex0331$supplement=="Fe3",]

或者与split一起,产生一个列表:

split(ex0331,ex0331$supplement)

您可以做的另一件事是使用tapply按因子分割然后执行功能:

tapply(ex0331$iron,ex0331$supplement,mean)
        Fe3         Fe4 
-0.15443861 -0.01308835 

也可以使用plyr包,它包含大量有用的功能。例如:

library(plyr)
daply(ex0331,.(supplement),function(x)mean(x[1]))
        Fe3         Fe4 
-0.15443861 -0.01308835 

修改

在回答编辑过的问题时,您可以通过以下方式获取每个补充剂的铁记录:

ex0331 <- data.frame( iron=abs(rnorm(36)), supplement=c("Fe3","Fe4"))

tapply(ex0331$iron,ex0331$supplement,log)

plyr

library(plyr)
dlply(ex0331,.(supplement),function(x)log(x$iron))

两者都在列表中返回。我确信有一种比plyr示例中的包装函数更简单的方法。