找到最小值并用r中的字符串替换

时间:2016-02-17 12:08:35

标签: r replace

我有一张海洋学数据,其中CTD演员/电台名称在一列中,深度在另一列中。它看起来像这样

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

现在我想找到每个演员的最小和最大深度,并分别用“surface”和“bottom”替换值。结果应如下所示:

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

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

4 个答案:

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

答案 1 :(得分:1)

如果每个'强制转换'只有一个最小值/最大值,则另一个选项是使用data.table。将'data.frame'转换为'data.table'(setDT(is)),按'cast'分组,我们order'深度',并通过将'surface'连接到''来创建新列“深度”元素除了最后一个,后跟“底部”。

 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]

答案 2 :(得分:1)

您还可以使用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))]

want$depth

但请注意{{1}}中的字符值,如@docendo discimus所述。

答案 3 :(得分:0)

使用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"