根据值

时间:2016-01-13 10:19:35

标签: r

我有以下数据:

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

但是希望有一种没有循环的方法。我的实际数据比这大得多,所以如果我必须保持循环,则需要很长时间。

2 个答案:

答案 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中执行此操作。首先使用datesplit分割数据框,然后使用which.min查找每个列表中的最小值。

sapply(split(d, d$date), function(d) d[which.min(d$height), 3])

# 1976-04-27 1976-04-28 
#         1          7