【问题标题】:Sort across rows to obtain three largest values跨行排序以获得三个最大值
【发布时间】:2019-02-05 08:17:37
【问题描述】:

有一个伤害分数叫ISS score

我有一个根据 pt ID 分行的伤害数据表。

我想获取 6 个伤害列的前三个值。

列值范围为 0-5。

pt_id head face abdo pelvis Extremity External
1    4    0    0    1    0    3
2    3    3    5    0    3    2
3    0    0    2    1    1    1
4    2    0    0    0    0    1
5    5    0    0    2    0    1

我上面例子的输出是

pt-id n1 n2 n3
1    4    3    1
2    5    3    3
3    2    1    1
4    2    1    0
5    5    2    1

值可以在列表或新列中,因为从那时起计算分数很简单。

我原以为我可以为 6 个伤害列创建一个列表,然后对每个列表进行排序以获取前三个值。我的代码是:

ais$ais_list <- setNames(split(ais[,2:7], seq(nrow(ais))), rownames(ais))

但我很难将排序应用于数据框中的列表,因为不幸的是我的数据集中的一些数据包含 NA 值

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用apply row-wise 和sort 数据框,并且每行只取前三个值。

    cbind(df[1], t(apply(df[-1], 1, sort, decreasing = TRUE)[1:3, ]))
    
    #  pt_id 1 2 3
    #1     1 4 3 1
    #2     2 5 3 3
    #3     3 2 1 1
    #4     4 2 1 0
    #5     5 5 2 1
    

    由于某些值可能包含NA,我们最好使用匿名函数applysort,然后使用head 取前3 个值。

    cbind(df[1], t(apply(df[-1], 1, function(x) head(sort(x, decreasing = TRUE), 3))))
    

    tidyverse 选项首先是 gather 数据,arrange 它按降序排列,每行只选择前三个值。然后我们将injury 列替换为我们想要的列名,最后将spread 数据恢复为宽格式。

    library(tidyverse)
    
    df %>%
      gather(injury, value, -pt_id) %>%
      arrange(desc(value)) %>%
      group_by(pt_id) %>%
      slice(1:3) %>%
      mutate(injury = 1:3) %>%
      spread(injury, value)
    
    #  pt_id   `1`   `2`   `3`
    #  <int> <int> <int> <int>
    #1     1     4     3     1
    #2     2     5     3     3
    #3     3     2     1     1
    #4     4     2     1     0
    #5     5     5     2     1
    

    【讨论】:

    • 谢谢。在 2000 行的真实数据集上,cbind 的答案非常慢。但是,tidyverse 的答案效果很好,而且速度非常快。您能否为我澄清为什么使用变量伤害但不是列名。它只是数据框中列的名称吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多