首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按属性对行进行分组

按属性对行进行分组
EN

Stack Overflow用户
提问于 2010-12-01 11:40:13
回答 3查看 4.2K关注 0票数 3

我有一个数据框,其中包含学生到各个班级迟到的数据。每一行都包含有关迟到学生及其班级的数据:班级日期和时间、班级名称、班级规模、迟到分钟数以及学生性别。为了得到所有班级迟到学生的总百分比,我需要计算行数(迟到学生),并将其与上课的学生总数进行比较。

我不能简单地将所有行的班级大小相加;这将对给定班级的学生进行多次计数,班级中每个迟到的学生一次。取而代之的是,我只需要为班级的每次会议计算一次班级人数。

示例

关键:迟到分钟数,班名,出勤人数,迟到学生性别,迟到分钟数。

代码语言:javascript
复制
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个迟到的学生。我如何确保每次班会的班级人数只计算一次?

EN

回答 3

Stack Overflow用户

发布于 2010-12-01 12:10:59

不同的函数用于计算延迟总和和班级大小。需要使用“粘贴”策略来创建数据和类名的唯一组合:

代码语言:javascript
复制
>  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:

代码语言:javascript
复制
>  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
票数 1
EN

Stack Overflow用户

发布于 2010-12-01 17:57:54

编辑:我的解决方案可以变得非常简单,只需先以每行为基础计算微不足道的% late,然后使用aggregate()按日期和类别对这些百分比求和:

代码语言:javascript
复制
> 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()通过几个步骤完成此操作

首先,获取每节课的迟到学生数量:

代码语言:javascript
复制
summ <- with(df, aggregate(MinsLate, by = list(Date = Date, Class = Class),
                           FUN = length))
names(summ)[3] <- "nLate"

这给了我们一个起点

代码语言:javascript
复制
> head(summ)
        Date Class nLate
1 2010-11-16 Radar     5
2 2010-11-12 Stats     3
3 2010-11-15 Stats     3

然后形成班级大小:

代码语言:javascript
复制
summ$Size <- with(df, aggregate(Size, by = list(Date = Date, Class = Class),
                                FUN = unique)$x)

这就把我们带到这里:

代码语言:javascript
复制
> 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

然后计算延迟百分比:

代码语言:javascript
复制
summ <- within(summ, pcLate <- 100 * (nLate / Size))

这会导致:

代码语言:javascript
复制
> 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

如果您经常需要这样做,请将其封装到一个函数中

代码语言:javascript
复制
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
}

这为我们完成了所有步骤:

代码语言:javascript
复制
> 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
票数 1
EN

Stack Overflow用户

发布于 2010-12-01 21:33:27

继续@Gavin的评论re:冗余输出,使用摘要:

代码语言:javascript
复制
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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4320980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档