我有一个数据框,其中包含有关学生迟到各种课程的数据。每行包含有关已故学生及其班级的数据:班级的日期和时间,班级名称,班级人数,迟到的分钟数以及学生的性别。为了获得所有课程的迟到学生的总百分比,我需要计算行数(已故学生)并将其与上课的学生总数进行比较。
我不能简单地将所有行的类大小相加;这将计算一个特定班级的学生几次,每班一次为每个已故的学生。相反,我需要为每次班级会议计算每个班级大小一次。
重点:迟到的分钟,课堂名称,出勤的学生,迟到的学生的性别,迟到的分钟。
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个迟到的学生。我怎样才能确保每个班级会议的班级人数只计算一次?
答案 0 :(得分:2)
如果我理解你想要什么,这对于plyr包更容易,而不是tapply或因为它理解多变量分组的含义。例如:
ddply(df, .(DATE,CLASS), transform, PERCENT_LATE=length(MINUTES.LATE)/CLASS.SIZE))
这里的长度参数可以是任何列名。 ddply将为DATE和CLASS因子级别的每个组合拆分数据帧。然后,每个迷你数据帧中的行数应该对应于已有多少学生(因为每个已故学生都有一个条目)。这就是长度(任何变量)的来源。将它除以分数的类大小列。
答案 1 :(得分:1)
和数和晚期的不同函数。需要使用“粘贴”策略来创建数据和类名称的唯一组合:
> 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
或使用聚合:
> 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
答案 2 :(得分:1)
编辑:首先通过计算每行基础上的琐碎%%,然后使用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
答案 3 :(得分:1)
继续关注@Gavin的评论:冗余输出,使用摘要:
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.73