【问题标题】:How do I filter a data.frame in R by categorical variable?如何通过分类变量过滤 R 中的 data.frame?
【发布时间】:2011-06-30 11:19:35
【问题描述】:

刚学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 操作文档都是针对数字变量而不是分类变量。

【问题讨论】:

  • 不清楚您所说的“log() 按组函数”是什么意思——log() 不是汇总函数,而 mean()sd() 是汇总函数(即它们产生一个向量输入的结果)。对于像log() 这样的函数,您可能只是想使用日志函数转换Iron 变量?或者,也许您想获取log(Iron) 数量中的mean()?如果您只是在寻找另一列LogIron,则无需按Supplement 分组——您只需将Iron 列中的每个条目转换为Log(Iron)...请参阅下面的编辑。

标签: r statistics dataframe


【解决方案1】:

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

> 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 列,其中每个条目是Iron 值的log(),您只需使用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

【讨论】:

    【解决方案2】:

    您可以通过索引或使用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 示例中的包装函数更简单的方法。

    【讨论】:

    • 非常好,谢谢!问题:原始子集中的“iron=rnorm(36)”在做什么?
    • 那只是为了模拟一些数据来玩。
    • 啊,好的。我已经在那个 data.frame 中获得了数据。所以我假设我真正想要的是 newdata
    • 它旨在模拟您已有的数据集:ex0331,它有一个包含数字的 iron 列和一个包含数字的因子列 supplement。所以你不需要创建一个新的 data.frame
    • @SachaEpskamp 是否有任何方法可以查看是否有任何变量需要在数据框中进行分解,而无需我们手动分解它们?我们如何知道是否有任何分类变量应该编码为 data.frame 中的因素?
    猜你喜欢
    • 1970-01-01
    • 2021-01-01
    • 2013-09-25
    • 2019-01-23
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    相关资源
    最近更新 更多