【问题标题】:How can i manipulate data within a factor level by a subset of another factor in that level in a dataframe without loops如何在没有循环的情况下通过数据框中该级别中另一个因子的子集来操作因子级别内的数据
【发布时间】:2017-09-28 10:29:39
【问题描述】:

我有一个由多个样品运行(样品 a、b、c、d)的吸收光谱组成的数据框,其中 Ydata 是波长,Xdata 是吸收。我通过从感兴趣的峰减去安静波长范围内的平均吸收来计算基线校正吸收。

简化的数据框:

DF <- data.frame(
  group = rep(c("a", "b", "c", "d"),each=10),
  Ydata = rep(1:10, times = 4),
  Xdata = c(seq(1,10,1),seq(5,50,5),seq(20,11,-1),seq(0.3,3,0.3)),
  abscorr = NA
)

我需要通过减去运行中子集波长范围的平均值来校正每个样本运行。我一直这样做:

for (i in 1:length(levels(DF$group))){
  sub1 <- subset(DF, group == levels(DF$group)[i], select = c(group, Ydata, 
  Xdata));
  sub2 <- subset(sub1, Ydata > 4 & Ydata < 8, select = c(group, Ydata, 
  Xdata));
  sub1$abscorr <- sub1$Xdata - mean(sub2$Xdata);
  DF <- rbind(sub1, DF);
}

然后整理所有的 'NA's

DF <- na.omit(DF)

使用循环显然很笨拙。对于大型数据集,是否有更好的方法来完成这项任务?也许dplyr?

【问题讨论】:

    标签: r loops dplyr plyr


    【解决方案1】:

    试试dplyr:

    DF %>%
        group_by(group) %>%
        mutate(abscorr = Xdata - mean(Xdata[Ydata < 8 & Ydata > 4]))
    

    【讨论】:

    • 感谢 MT!工作一种享受。我无法理解 dplyr 包是如何工作的。
    【解决方案2】:

    我相信这会成功。

    fun <- function(x){
        x$Xdata - mean(x[which(x$Ydata > 4 & x$Ydata < 8), "Xdata"])
    }
    DF$abscorr <- do.call(c, lapply(split(DF, DF$group), fun))
    

    注意,我测试的时候all.equal给了我一系列的不同,即两个结果的属性不同。所以我运行了以下内容。

    fun <- function(x){
        x$Xdata - mean(x[which(x$Ydata > 4 & x$Ydata < 8), "Xdata"])
    }
    DF2 <- DF
    DF2$abscorr <- do.call(c, lapply(split(DF2, DF2$group), fun))
    
    all.equal(DF[order(DF$group, DF$Ydata), ], DF2)
    # [1] "Attributes: < Names: 1 string mismatch >"                                         
    # [2] "Attributes: < Length mismatch: comparison on first 2 components >"                
    # [3] "Attributes: < Component 2: names for target but not for current >"                
    # [4] "Attributes: < Component 2: Attributes: < Modes: list, NULL > >"                   
    # [5] "Attributes: < Component 2: Attributes: < Lengths: 1, 0 > >"                       
    # [6] "Attributes: < Component 2: Attributes: < names for target but not for current > >"
    # [7] "Attributes: < Component 2: Attributes: < current is not list-like > >"            
    # [8] "Attributes: < Component 2: target is omit, current is numeric >"                  
    # [9] "Component “abscorr”: Modes: numeric, logical"                                     
    #[10] "Component “abscorr”: target is numeric, current is logical"
    

    如您所见,abscorr 的计算值没有区别,只有属性不同。其中,na.omit 属性或rownames 存在差异。如果我是你,我不会担心,因为 abscorr 的值是相等的。

    编辑。
    请注意,如果我对DF 进行排序,然后将问题属性设置为NULL,则all.equal 和更严格的identical 返回TRUE

    DF1 <- DF[order(DF$group, DF$Ydata), ]  # Modify a copy, keep the original
    row.names(DF1) <- NULL
    attr(DF1, "na.action") <- NULL
    
    all.equal(DF1, DF2)
    #[1] TRUE
    identical(DF1, DF2)
    #[1] TRUE
    

    【讨论】:

    • 感谢 Rui - 一个不错的 base-R 解决方案!
    猜你喜欢
    • 2014-02-11
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 2011-03-31
    相关资源
    最近更新 更多