【问题标题】:Sorting R data frame by number of factors levels按因子级别数对 R 数据框进行排序
【发布时间】:2016-04-03 13:26:04
【问题描述】:

我有一个包含三列的巨大数据框:

   Surgeon Length  Surg. Date
    John    75   2015-07-06
    Max     120  2015-06-22
    Max     190  2015-01-26
    David   40   2015-11-04
    David   25   2015-04-21
    David   50   2015-12-11
    Andrey  210  2015-03-15
    Vincent 180  2015-01-30
    Vincent 180  2015-06-10

我想根据外科医生做了多少手术对其进行排序。如果两名外科医生做了相同数量的手术,那么手术日期应该决定排名。 输出应如下所示:

   Surgeon Length  Surg. Date
    Andrey  210  2015-03-15
    John    75   2015-07-06
    Max     190  2015-01-26
    Max     120  2015-06-22
    Vincent 180  2015-01-30
    Vincent 180  2015-06-10
    David   25   2015-04-21
    David   40   2015-11-04
    David   50   2015-12-11

Andrey 和 John 的名字在表格中出现一次,所以他们排在第一位,但 Andrey 的日期更早,因此他是表格中的第一位。然后是 Max 和 Vincent,他们都做了 2 次手术。然后是大卫和 3。

有没有简单的方法可以做到这一点?

【问题讨论】:

    标签: r sorting dataframe data.table


    【解决方案1】:
    dd <- read.table(header = TRUE, text = "Surgeon Length  'Surg. Date'
    John    75   2015-07-06
    Max     120  2015-06-22
    Max     190  2015-01-26
    David   40   2015-11-04
    David   25   2015-04-21
    David   50   2015-12-11
    Andrey  210  2015-03-15
    Vincent 180  2015-01-30
    Vincent 180  2015-06-10", check.names = FALSE)
    

    我们可以设置Surgeon 的级别,以便 r 为我们处理排序。如果我们将外科医生制成表格并对表格进行排序,您可以看到表格名称是按您想要的顺序排列的,因此我们只需将此顺序设置为levels(Surgeon) 的顺序,而不是默认的(字母顺序)。

    然后我们只需添加一个额外的按日期排序。

    sort(tbl <- table(dd$Surgeon))
     # Andrey    John     Max Vincent   David 
     #      1       1       2       2       3 
    

    对于有领带的人,我们还可以添加一个排序因子与第一个日期

    (lvls <- names(tbl)[order(tbl, tapply(as.Date(dd$`Surg. Date`), dd$Surgeon, min))])
    # [1] "Andrey"    "John"  "Max"     "Vincent" "David"  
    
    dd$Surgeon <- factor(dd$Surgeon, levels = lvls)
    
    dd[order(dd$Surgeon, dd$`Surg. Date`), ]
    #   Surgeon Length Surg. Date
    # 7  Andrey    210 2015-03-15
    # 1    John     75 2015-07-06
    # 3     Max    190 2015-01-26
    # 2     Max    120 2015-06-22
    # 8 Vincent    180 2015-01-30
    # 9 Vincent    180 2015-06-10
    # 5   David     25 2015-04-21
    # 4   David     40 2015-11-04
    # 6   David     50 2015-12-11
    

    使用@akrun 的dplyr 解决方案,您可以更高效地执行类似的方法。

    library('dplyr')
    dd %>%
      group_by(Surgeon) %>%
      mutate(n=n()) %>%
      ungroup() %>%
      arrange(n, Surgeon, `Surg. Date`) %>%
      select(-n)
    
    #   Surgeon Length Surg. Date
    #    (fctr)  (int)     (fctr)
    # 1  Andrey    210 2015-03-15
    # 2    John     75 2015-07-06
    # 3     Max    190 2015-01-26
    # 4     Max    120 2015-06-22
    # 5 Vincent    180 2015-01-30
    # 6 Vincent    180 2015-06-10
    # 7   David     25 2015-04-21
    # 8   David     40 2015-11-04
    # 9   David     50 2015-12-11
    

    或者如果您像上面那样订购了因子水平,您可以这样做

    dd %>% arrange(Surgeon, `Surg. Date`)
    

    使用data.table,您仍然可以使用表/因子级别方法并设置键,但我不确定这是否是 data.table 方式(即,唯一的开销是 table,这似乎对于大型向量来说非常快)

    library('data.table')
    dd$Surgeon <- factor(dd$Surgeon, levels = names(sort(table(dd$Surgeon))))
    setDT(dd, key = c('Surgeon', 'Surg. Date'))
    
    #    Surgeon Length Surg. Date
    # 1:  Andrey    210 2015-03-15
    # 2:    John     75 2015-07-06
    # 3:     Max    190 2015-01-26
    # 4:     Max    120 2015-06-22
    # 5: Vincent    180 2015-01-30
    # 6: Vincent    180 2015-06-10
    # 7:   David     25 2015-04-21
    # 8:   David     40 2015-11-04
    # 9:   David     50 2015-12-11
    

    【讨论】:

    • @DavidArenburg 看到数据表编辑,你会怎么做?
    • 当外科医生进行 1 次手术时它不起作用,然后它按名称而不是日期排序。例如,如果我们交换 Andrey 和 John 的日期,Andrey 仍然是排名第一的。
    • 对于 data.table 方法,您可以将级别设置为DT[, .(.N, min(Surg.Date)), by=Surgeon][order(N, V2), Surgeon]
    • @Lanza 查看编辑,您可以添加因子排序的另一个条件并保持其他所有内容相同
    猜你喜欢
    • 1970-01-01
    • 2013-10-29
    • 1970-01-01
    • 2014-02-11
    • 2022-01-07
    • 2021-12-27
    • 1970-01-01
    • 2018-10-09
    • 2019-10-11
    相关资源
    最近更新 更多