例如,如果我有这些数据:
ID Value
1 2
1 2
1 3
1 4
1 10
2 9
2 9
2 12
2 13
我的目标是找到每个ID子集的最小值,我希望该数字位于ID组的第一行,而其他行保持空白,这样:
ID Value Start
1 2 2
1 2
1 3
1 4
1 10
2 9 9
2 9
2 12
2 13
我的第一直觉是使用
为ID创建索引A <- transform(A, INDEX=ave(ID, ID, FUN=seq_along)) ## A being the name of my data
由于我是菜鸟,我现在陷入困境。对于每个ID = n,我想找到该ID子集的min(A $ Value)并将其置于ID = n和INDEX = 1的单元匹配条件中。
非常感谢任何帮助!对不起,我一直在问问题:(
答案 0 :(得分:3)
这是一个解决方案:
within(A, INDEX <- "is.na<-"(ave(Value, ID, FUN = min), c(FALSE, !diff(ID))))
ID Value INDEX
1 1 2 2
2 1 2 NA
3 1 3 NA
4 1 4 NA
5 1 10 NA
6 2 9 9
7 2 9 NA
8 2 12 NA
9 2 13 NA
<强>更新强>
工作原理?命令ave(Value, ID, FUN = min)
将min
函数应用于Value
的{{1}}的每个子集。对于该示例,它返回五次ID
和四次2
的向量。由于每个子集中除第一个之外的所有值都应为9
,因此函数NA
将替换"is.na<-"
定义的逻辑索引处的所有值。如果值与前一个值相同,则此索引为c(FALSE, !diff(ID))
。
答案 1 :(得分:2)
你快到了。我们只需要创建自定义函数而不是seq_along
并将value
分割为ID
(ID
除ID
之外)。
first_min <- function(x){
nas <- rep(NA, length(x))
nas[which.min(x)] <- min(x, na.rm=TRUE)
nas
}
此函数生成NA的向量,并用最小值Value
替换第一个元素。
transform(dat, INDEX=ave(Value, ID, FUN=first_min))
## ID Value INDEX
## 1 1 2 2
## 2 1 2 NA
## 3 1 3 NA
## 4 1 4 NA
## 5 1 10 NA
## 6 2 9 9
## 7 2 9 NA
## 8 2 12 NA
## 9 2 13 NA
答案 2 :(得分:1)
您可以使用tapply one-liner
来实现这一目标df$Start<-as.vector(unlist(tapply(df$Value,df$ID,FUN = function(x){ return (c(min(x),rep("",length(x)-1)))})))
答案 3 :(得分:0)
我一直回到这个问题,上面的答案对我帮助很大。 初学者也有一个基本的解决方案:
A$Start<-NA
A[!duplicated(A$ID),]$Start<-A[!duplicated(A$ID),]$Value
感谢。