Table 每个百分位数的同行平均分
Table of average score of peer per percentile
我是 R 的新手,所以我对我的解决方案的最优性很感兴趣。即使有效,它也可能(有点)长,我希望得到您的建议,看看 "way I solved it" 是否为 "the best",它可以帮助我学习 R 中的新技术和功能。
我有一个关于学生的数据集,由他们 id
识别,我有他们匹配的学校和他们在特定测试中获得的分数(简称:3 个变量 id、匹配和分数) .
我需要构建以下内容table:对于分数在两个百分位数之间的学生,我需要计算他们匹配的学校学生平均分数的平均分数(学生之间)到(所以对于每所学校,我取与其匹配的学生的平均分数,然后我计算百分位数 类 的平均值的平均值,是的,学校的平均值可能在此计算中出现两次)。用英语它允许我回答:"A student belonging to the x-th
percentile in terms of score will be in average matched to a school with this average quality".
这里是图片中的例子:
所以在那种情况下,如果我取中位数 (15) 作为拆分(而不是百分位数),我想获得:
[0,15] : 9.5
(15,24] : 20.25
所以对于分数在 0 到 15 之间的学生,我取他们匹配的学校的平均分数的平均值(注意 b 平均值会出现两次,但没关系)。
这是我的做法:
match <- c(a,b,a,b,c)
score <- c(18,4,15,8,24)
scoreQuant <- cut(score,quantile(score,probs=seq(0,1,0.1),na.rm=TRUE))
AvgeSchScore <- tapply(score,match,mean,na.rm=TRUE)
AvgScore <- 0
for(i in 1:length(score)) {
AvgScore[i] <- AvgeSchScore[match[i]]
}
results <- tapply(AvgScore,scoreQuant,mean,na.rm = TRUE)
如果你有更直接的方法.. 或者我认为缺点是 3) 使用循环,也许 apply()
更好?但我不确定如何在这里使用它(我尝试编写自己的函数但它崩溃了所以我 "bruted force it")。
谢谢:)
主要修复是用以下方法消除 for 循环:
AvgScore <- AvgeSchScore[match]
R 允许您以其他语言无法实现的方式进行子集化。 tapply
函数输出您分组依据的因素的名称。我们正在使用 match
的这些名称来子集 AvgeScore
.
data.table
如果您想尝试 data.table
,您可能会发现速度有所提高。
library(data.table)
match <- c("a","b","a","b","c")
score <- c(18,4,15,8,24)
dt <- data.table(id=1:5, match, score)
scoreQuant <- cut(dt$score,quantile(dt$score,probs=seq(0,1,0.1),na.rm=TRUE))
dt[, AvgeScore := mean(score), match][, mean(AvgeScore), scoreQuant]
# scoreQuant V1
#1: (17.4,19.2] 16.5
#2: NA 6.0
#3: (12.2,15] 16.5
#4: (7.2,9.4] 6.0
#5: (21.6,24] 24.0
可能比base R
快。如果NA行中的值让您感到困扰,您可以在之后删除它。
我是 R 的新手,所以我对我的解决方案的最优性很感兴趣。即使有效,它也可能(有点)长,我希望得到您的建议,看看 "way I solved it" 是否为 "the best",它可以帮助我学习 R 中的新技术和功能。
我有一个关于学生的数据集,由他们 id
识别,我有他们匹配的学校和他们在特定测试中获得的分数(简称:3 个变量 id、匹配和分数) .
我需要构建以下内容table:对于分数在两个百分位数之间的学生,我需要计算他们匹配的学校学生平均分数的平均分数(学生之间)到(所以对于每所学校,我取与其匹配的学生的平均分数,然后我计算百分位数 类 的平均值的平均值,是的,学校的平均值可能在此计算中出现两次)。用英语它允许我回答:"A student belonging to the x-th
percentile in terms of score will be in average matched to a school with this average quality".
这里是图片中的例子:
所以在那种情况下,如果我取中位数 (15) 作为拆分(而不是百分位数),我想获得:
[0,15] : 9.5
(15,24] : 20.25
所以对于分数在 0 到 15 之间的学生,我取他们匹配的学校的平均分数的平均值(注意 b 平均值会出现两次,但没关系)。
这是我的做法:
match <- c(a,b,a,b,c)
score <- c(18,4,15,8,24)
scoreQuant <- cut(score,quantile(score,probs=seq(0,1,0.1),na.rm=TRUE))
AvgeSchScore <- tapply(score,match,mean,na.rm=TRUE)
AvgScore <- 0
for(i in 1:length(score)) {
AvgScore[i] <- AvgeSchScore[match[i]]
}
results <- tapply(AvgScore,scoreQuant,mean,na.rm = TRUE)
如果你有更直接的方法.. 或者我认为缺点是 3) 使用循环,也许 apply()
更好?但我不确定如何在这里使用它(我尝试编写自己的函数但它崩溃了所以我 "bruted force it")。
谢谢:)
主要修复是用以下方法消除 for 循环:
AvgScore <- AvgeSchScore[match]
R 允许您以其他语言无法实现的方式进行子集化。 tapply
函数输出您分组依据的因素的名称。我们正在使用 match
的这些名称来子集 AvgeScore
.
data.table
如果您想尝试 data.table
,您可能会发现速度有所提高。
library(data.table)
match <- c("a","b","a","b","c")
score <- c(18,4,15,8,24)
dt <- data.table(id=1:5, match, score)
scoreQuant <- cut(dt$score,quantile(dt$score,probs=seq(0,1,0.1),na.rm=TRUE))
dt[, AvgeScore := mean(score), match][, mean(AvgeScore), scoreQuant]
# scoreQuant V1
#1: (17.4,19.2] 16.5
#2: NA 6.0
#3: (12.2,15] 16.5
#4: (7.2,9.4] 6.0
#5: (21.6,24] 24.0
可能比base R
快。如果NA行中的值让您感到困扰,您可以在之后删除它。