我有一张海洋学数据,其中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()。 非常感谢帮助。 大卫
答案 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"