【问题标题】:find minima and replace with character string in r找到最小值并用 r 中的字符串替换
【发布时间】:2016-02-17 12:08:34
【问题描述】:

我有一个 df 的海洋学数据,其中一列是 CTD 演员/站名,另一列是深度。它看起来像这样

is <- data.frame(cast=c("a","a","a","b","b","b"), depth=c(10,20,30,5,15,25))

现在我想找到每次投射的最小和最大深度,并分别用“表面”和“底部”替换该值。结果应如下所示:

want <- data.frame(cast=c("a","a","a","b","b","b"), depth=c("surface",20,"bottom","surface",15,"bottom"))

我使用 aggregate() 来查找每个最小值/最大值,并尝试使用 ifelse() 和 for 循环来替换值,但无法使其工作。 非常感谢您的帮助。 大卫

【问题讨论】:

    标签: r replace


    【解决方案1】:

    这是一种经典的拆分/应用/组合方法。但是,您应该知道,通过在数字列中引入字符串,整个列将被转换为字符。

    do.call(rbind, lapply(split(is, is$cast), transform, depth = 
     ifelse(depth == min(depth), "surface", ifelse(depth == max(depth), "bottom", depth))))
    #    cast   depth
    #a.1    a surface
    #a.2    a      20
    #a.3    a  bottom
    #b.4    b surface
    #b.5    b      15
    #b.6    b  bottom
    

    为避免类型转换,您可以考虑另一种方法,例如:

    do.call(rbind, lapply(split(is, is$cast), transform, 
                 surface = depth == min(depth), 
                 bottom  = depth == max(depth)))
    #    cast depth surface bottom
    #a.1    a    10    TRUE  FALSE
    #a.2    a    20   FALSE  FALSE
    #a.3    a    30   FALSE   TRUE
    #b.4    b     5    TRUE  FALSE
    #b.5    b    15   FALSE  FALSE
    #b.6    b    25   FALSE   TRUE
    

    【讨论】:

    • 感谢@docendo discimus。这行得通。我对字符的转换没有问题。无论如何,我将演员表和深度粘贴在一起,以便为每个样本设置一个唯一标识符。但是你能解释一下,transform 在这里做了什么吗?
    【解决方案2】:

    如果每个“演员”只有一个最小值/最大值,另一种选择是使用data.table。将'data.frame'转换为'data.table'(setDT(is)),按'cast'分组,我们order'depth',并通过将'surface'连接到'depth'的元素来创建新列' 除了最后一个,后面跟着 'bottom'。

     library(data.table)
     setDT(is)[order(depth), depth1 := c('surface',
                            depth[2:(.N-1)], 'bottom') ,cast]
     is
     #  cast depth  depth1
     #1:    a    10 surface
     #2:    a    20      20
     #3:    a    30  bottom
     #4:    b     5 surface
     #5:    b    15      15
     #6:    b    25  bottom
    

    如果在某些情况下,'cast' 只有一个观察值

     setDT(is)[order(depth), depth1 := if(.N > 1) 
        c('surface', depth[2:(.N-1)], 'bottom') else depth ,cast]
    

    【讨论】:

      【解决方案3】:

      你也可以使用tapply:

      newdepth <- c(is$cast,is$depth)
      newdepth[is==tapply(is$depth,is$cast,max)] <- "bottom"
      newdepth[is==tapply(is$depth,is$cast,min)] <- "surface"
      
      want <- is
      want$depth <- newdepth[-(1:nrow(want))]
      

      但请注意@docendo discimus 所述的want$depth 中的字符值。

      【讨论】:

        【解决方案4】:

        使用by 的类似方法。

        # First cbind an index
        is$index <- 1:nrow(is)
        
        # then find the max and min and return the indeces
        foo <- function(x) cbind(min= x$index[which.min(x$depth)], max= x$index[which.max(x$depth)])
        gr <- do.call(rbind, by(is, list(is$cast), FUN=  foo))
        
        # subset the extremes and replace the values with your choice. 
        is[gr[,1], "depth"] <- "surface"
        is[gr[,2], "depth"] <- "bottom"
        

        【讨论】:

          猜你喜欢
          • 2011-03-12
          • 1970-01-01
          • 2018-03-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-06-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多