我有以下数据:
d <- data.frame(date = c('1976-04-27','1976-04-27','1976-04-27',
'1976-04-28','1976-04-28','1976-04-28'),
height = c(0.1,0.2,0.3,1,2,3),
val = c(1,5,8,7,4,6))
> d
date height val
1 1976-04-27 0.1 1
2 1976-04-27 0.2 5
3 1976-04-27 0.3 8
4 1976-04-28 1.0 7
5 1976-04-28 2.0 4
6 1976-04-28 3.0 6
每个独特的日期&#39;我想找到&#39; val&#39;这对应于min&#39; height&#39;。因此,我最终想要的答案是1和7.我可以通过循环实现所需的结果:
tt <- sapply(as.Date(d[,1]), unique)
uniq_tt <- unique(tt)
a <- NA
for (i in 1:length(uniq_tt)){
indx <- tt == uniq_tt[i]
d2 <- d[indx,]
a[i] <- d2[which.min(d2[,2]),3]
}
> a
[1] 1 7
但是希望有一种没有循环的方法。我的实际数据比这大得多,所以如果我必须保持循环,则需要很长时间。
答案 0 :(得分:4)
我们可以通过各种方式在多个小组中这样做。一个选项是data.table
。将'data.frame'转换为'data.table'(setDT(d)
),按'date'分组,我们找到'height'的'min'值的索引并使用它来过滤相应的'val'行。提取输出列($V1
)以获取'val'的向量。
library(data.table)
setDT(d)[, val[which.min(height)], by = date]$V1
#[1] 1 7
或者使用相同的方法dplyr
。
library(dplyr)
d %>%
group_by(date) %>%
summarise(Val= val[which.min(height)]) %>%
.$Val
使用base R
ave
方法
d$val[as.logical(with(d, ave(height, date,
FUN= function(x) x==min(x))))]
#[1] 1 7
答案 1 :(得分:3)
您可以使用sapply
在基地R中执行此操作。首先使用date
按split
分割数据框,然后使用which.min
查找每个列表中的最小值。
sapply(split(d, d$date), function(d) d[which.min(d$height), 3])
# 1976-04-27 1976-04-28
# 1 7