我有一个数据框,其中包含学生到各个班级迟到的数据。每一行都包含有关迟到学生及其班级的数据:班级日期和时间、班级名称、班级规模、迟到分钟数以及学生性别。为了得到所有班级迟到学生的总百分比,我需要计算行数(迟到学生),并将其与上课的学生总数进行比较。
我不能简单地将所有行的班级大小相加;这将对给定班级的学生进行多次计数,班级中每个迟到的学生一次。取而代之的是,我只需要为班级的每次会议计算一次班级人数。
示例
关键:迟到分钟数,班名,出勤人数,迟到学生性别,迟到分钟数。
11/12/10 Stats 30 M 1
11/12/10 Stats 30 M 1
11/12/10 Stats 30 M 1
11/15/10 Stats 40 F 3
11/15/10 Stats 40 F 3
11/15/10 Stats 40 F 3
11/16/10 Radar 22 M 2
11/16/10 Radar 22 M 2
11/16/10 Radar 22 M 2
11/16/10 Radar 22 M 2
11/16/10 Radar 22 M 2在这种情况下,有三个不同的班会和11个迟到的学生。我如何确保每次班会的班级人数只计算一次?
发布于 2010-12-01 12:10:59
不同的函数用于计算延迟总和和班级大小。需要使用“粘贴”策略来创建数据和类名的唯一组合:
> sum_late <- tapply( tst$V5, paste(tst$V1, tst$V2, sep="_"), length)
> csize <- tapply( tst$V3, paste(tst$V1, tst$V2, sep="_"), head,1)
> pct_late <- 100*sum_late/csize
> pct_late
11/12/10_Stats 11/15/10_Stats 11/16/10_Radar
10.00000 7.50000 22.72727 或者使用aggregate:
> dfcount <- aggregate( tst$V5, list(tst$V1, tst$V2), length)
> dfcount$pct <- 100*aggregate( tst$V5, list(tst$V1, tst$V2), length)$x/aggregate( tst$V3, list(tst$V1, tst$V2), head,1)$x
> dfcount
Group.1 Group.2 x pct
1 11/16/10 Radar 5 22.72727
2 11/12/10 Stats 3 10.00000
3 11/15/10 Stats 3 7.50000发布于 2010-12-01 17:57:54
编辑:我的解决方案可以变得非常简单,只需先以每行为基础计算微不足道的% late,然后使用aggregate()按日期和类别对这些百分比求和:
> df2 <- within(df, pcLate <- 100 * (1 / Size))
> df2
Date Class Size Sex MinsLate pcLate
1 2010-11-12 Stats 30 M 1 3.333333
2 2010-11-12 Stats 30 M 1 3.333333
3 2010-11-12 Stats 30 M 1 3.333333
4 2010-11-15 Stats 40 F 3 2.500000
5 2010-11-15 Stats 40 F 3 2.500000
6 2010-11-15 Stats 40 F 3 2.500000
7 2010-11-16 Radar 22 M 2 4.545455
8 2010-11-16 Radar 22 M 2 4.545455
9 2010-11-16 Radar 22 M 2 4.545455
10 2010-11-16 Radar 22 M 2 4.545455
11 2010-11-16 Radar 22 M 2 4.545455
> with(df2, aggregate(pcLate, by = list(Date = Date, Class = Class), sum))
Date Class x
1 2010-11-16 Radar 22.72727
2 2010-11-12 Stats 10.00000
3 2010-11-15 Stats 7.50000原始答案:
假设df包含您提供的示例数据,我们可以使用aggregate()通过几个步骤完成此操作
首先,获取每节课的迟到学生数量:
summ <- with(df, aggregate(MinsLate, by = list(Date = Date, Class = Class),
FUN = length))
names(summ)[3] <- "nLate"这给了我们一个起点
> head(summ)
Date Class nLate
1 2010-11-16 Radar 5
2 2010-11-12 Stats 3
3 2010-11-15 Stats 3然后形成班级大小:
summ$Size <- with(df, aggregate(Size, by = list(Date = Date, Class = Class),
FUN = unique)$x)这就把我们带到这里:
> head(summ)
Date Class nLate Size
1 2010-11-16 Radar 5 22
2 2010-11-12 Stats 3 30
3 2010-11-15 Stats 3 40然后计算延迟百分比:
summ <- within(summ, pcLate <- 100 * (nLate / Size))这会导致:
> head(summ)
Date Class nLate Size pcLate
1 2010-11-16 Radar 5 22 22.72727
2 2010-11-12 Stats 3 30 10.00000
3 2010-11-15 Stats 3 40 7.50000如果您经常需要这样做,请将其封装到一个函数中
tardiness <- function(df) {
out <- with(df, aggregate(MinsLate, by = list(Date = Date, Class = Class),
FUN = length))
names(out)[3] <- "nLate"
out$Size <- with(df, aggregate(Size, by = list(Date = Date, Class = Class),
FUN = unique)$x)
out <- within(out, pcLate <- 100 * (nLate / Size))
out
}这为我们完成了所有步骤:
> tardiness(df)
Date Class nLate Size pcLate
1 2010-11-16 Radar 5 22 22.72727
2 2010-11-12 Stats 3 30 10.00000
3 2010-11-15 Stats 3 40 7.50000发布于 2010-12-01 21:33:27
继续@Gavin的评论re:冗余输出,使用摘要:
df.out <- ddply(x, .(DATE, CLASS), summarise
, NLATE = length(c(DATE, CLASS)) / 2
, SIZE = unique(CLASS.SIZE)
, PCLATE = 100 * (length(c(DATE, CLASS)) / 2 )/ unique(CLASS.SIZE)
)
> df.out
DATE CLASS NLATE SIZE PCLATE
1 11/12/10 Stats 3 30 10.00
2 11/15/10 Stats 3 40 7.50
3 11/16/10 Radar 5 22 22.73https://stackoverflow.com/questions/4320980
复制相似问题