我有一个包含2列的数据框,其中一列带有数字值,另一列带有名称。名称重复,但每次都有不同的值。
Data <- data.frame(
Value = c(1:10),
Name = rep(LETTERS, each=4)[1:10])
我想编写一个函数,它为每个名称取3个最高数字并计算平均值和中位数(如果没有3个值存在则抛出NA)然后获取每个名称的所有值并计算平均值和中位数。 我最初的尝试看起来像这样:
my.mean <- function (x,y){
top3.x <- ifelse(x > 3 , NA, x)
return(mean(top3.x), median(top3.x))
}
任何关于如何改进这一点的提示都将受到赞赏。
答案 0 :(得分:2)
我可能会为此推荐by
。
快速拼凑的东西可能看起来像这样(如果我理解你的问题):
myFun <- function(indf) {
do.call(rbind, with(indf, by(Value, Name, FUN=function(x) {
Vals <- head(sort(x, decreasing=TRUE), 3)
if (length(Vals) < 3) {
c(Mean = NA, Median = NA)
} else {
c(Mean = mean(Vals), Median = median(Vals))
}
})))
}
myFun(Data)
# Mean Median
# A 3 3
# B 7 7
# C NA NA
请注意,由于有多少参数被硬编码到函数中,因此它在此形式中不是一个非常有用的函数。只有当您的数据采用您共享的形式时,它才真正有用。
答案 1 :(得分:1)
这是一个data.table
解决方案,假设您的数据中没有任何其他NA:
require(data.table) ## 1.9.2+
setDT(Data) ## convert to data.table
Data[order(Name, -Value)][, list(m1=mean(Value[1:3]), m2=median(Value[1:3])), by=Name]
# Name m1 m2
# 1: A 3 3
# 2: B 7 7
# 3: C NA NA
答案 2 :(得分:0)
使用dplyr
library(dplyr)
myFun1 <- function(dat){
dat %>%
group_by(Name)%>%
arrange(desc(Value))%>%
mutate(n=n(), Value=ifelse(n<=3, NA_integer_, Value))%>%
summarize(Mean=mean(head(Value,3)), Median=median(head(Value,3)))
}
myFun1(Data)
#Source: local data frame [3 x 3]
# Name Mean Median
#1 A 3 3
#2 B 7 7
#3 C NA NA