每个观察结果的百分位数w/r/t分组变量

ecfdbz9o  于 2023-03-20  发布在  其他
关注(0)|答案(7)|浏览(130)

我有一些如下所示的数据。它是按变量“年份”分组的,我想提取 * 每个 * 观察值的分数百分位数,相对于它来自的年份,最好作为一个向量。

Year   Score
2001   89
2001   70
2001   72
2001   ...
..........
2004   87
2004   90

等等。
我该怎么做呢?聚合不起作用,我认为应用也不起作用。

pdtvr36n

pdtvr36n1#

根据Vince的解决方案,您还可以使用plyrby来执行此操作:

ddply(df, .(years), function(x) transform(x, percentile=ecdf(x$scores)(x$scores)))
wtlkbnrh

wtlkbnrh2#

使用ave

ave(d1$scores, d1$year, FUN=function(x) ecdf(x)(x))
zzoitvuj

zzoitvuj3#

我可能误会了,但我想可以这样做:

> years = c(2006, 2006, 2006, 2006, 2001, 2001, 2001, 2001, 2001)
> scores = c(13, 65, 23, 34, 78, 56, 89, 98, 100)
> tapply(scores, years, quantile)
$`2001`
  0%  25%  50%  75% 100% 
  56   78   89   98  100 

$`2006`
   0%   25%   50%   75%  100% 
13.00 20.50 28.50 41.75 65.00

是这样吗?
我指的是每个观察结果的实际百分比。-瑞安·罗萨里奥
编辑:
我想这可能会做到这一点:

> tapply(scores, years, function(x) { f = ecdf(x); sapply(x, f) })
$`2001`
[1] 0.4 0.2 0.6 0.8 1.0

$`2006`
[1] 0.25 1.00 0.50 0.75

使用您的数据:

> tapply(scores, years, function(x) { f = ecdf(x); sapply(x, f) })
$`2000`
[1] 0.3333333 0.6666667 1.0000000

$`2008`
[1] 0.5 1.0

编辑二:
这可能更快:

tapply(scores, years, function(x) { f = ecdf(x); f(x) })

f()已矢量化:-)
最后,修改,我保证:-)。如果你想要的名字:

> tapply(scores, years, function(x) { f = ecdf(x); r = f(x); names(r) <- x; r })
$`2000`
     1000      1700      2000 
0.3333333 0.6666667 1.0000000 

$`2008`
1500 2000 
 0.5  1.0
ef1yzkbh

ef1yzkbh4#

使用data.table也是非常直接的,只是为了完整性,也是找到data.table解决方案的一种简单方法。

library(data.table)
year <- rep(2001:2005, 2)
score <- round(rnorm(10, 35, 3))

dt <- data.table(year, score)

dt[, .(Percentile = ecdf(score)(score)), by = list(year)]
c6ubokkw

c6ubokkw5#

你也可以这样做:

# first I'll create two dummy variables (Year, Score)
year <- rep(2001:2005, 2)
score <- round(rnorm(10, 35, 3))

# then coerce variables to data frame
d <- data.frame(year, score)

# then you can use split() function to apply
# function to each stratum of grouping variable
sapply(split(score, year), function(x) quantile(x, probs=seq(.1, .9, .1)))

输出将如下所示:

2001 2002 2003 2004 2005
10%  34.3 32.1 34.3 29.6 36.1
20%  34.6 32.2 34.6 30.2 36.2
30%  34.9 32.3 34.9 30.8 36.3
40%  35.2 32.4 35.2 31.4 36.4
50%  35.5 32.5 35.5 32.0 36.5
60%  35.8 32.6 35.8 32.6 36.6
70%  36.1 32.7 36.1 33.2 36.7
80%  36.4 32.8 36.4 33.8 36.8
90%  36.7 32.9 36.7 34.4 36.9

如果你愿意,你可以利用t()函数来转置行和列。编写一个函数将是解决这类问题的好方法。我强烈推荐Hadley Wickam编写的plyr包。
希望这对你有帮助!祝你一切顺利!

dsekswqp

dsekswqp6#

我找到了一个方法,但它需要一个循环。

group.pctiles <- function(group.var, comparable) {
    unique.vals <- unique(group.var)
    pctiles <- vector(length = length(group.var))
    for (i in 1:length(unique.vals)) {
        slice <- which(group.var == unique.vals[i])
        F <- ecdf(comparable[slice])
        group.pctiles <- F(comparable[slice])
        pctiles[slice] <- group.pctiles
    }
    return(pctiles)
}

group.var是对数据进行分组的变量。在我的问题示例中,它是Year。comparable包含我们要查找其百分位数的值。在我的问题中,comparable是Score。
对于以下数据,我得到了以下结果:

Year,School,Fees
2000,10,1000
2008,1,1050
2008,4,2000
2000,3,1700
2000,1,2000

> group.pctiles(dat, dat$Year, dat$Fees)
[1] 0.3333333 0.5000000 1.0000000 0.6666667 1.0000000

然后,我可以将这些百分比重新绑定到原始数据框架中,以便进行分析、报告等。
有人有不需要循环的解决方案吗?

yqhsw0fo

yqhsw0fo7#

不如这样:

Year <- c(2000,2008,2008,2000,2000)
Fees <- c(1000,1050,2000,1700,2000)
dat <- data.frame(Fees,Year,result=NA)
res <- tapply(Fees,Year,function(x) rank(x,ties.method="max")/length(x))
for(i in 1:length(res))
   dat[Year==as.numeric(names(res)[i]),"result"] <-res[[i]]

其产生:

Fees Year    result
1 1000 2000 0.3333333
2 1050 2008 0.5000000
3 2000 2008 1.0000000
4 1700 2000 0.6666667
5 2000 2000 1.0000000

相关问题