【问题标题】:Indexing subgroups by sorted positions in R dataframe按 R 数据框中的排序位置索引子组
【发布时间】:2015-06-25 22:58:00
【问题描述】:

我有一个数据框,其中包含有关多个类别和一些相关变量的信息。它的形式是:

   ID       category     sales    score
   227          A         109       21
   131          A         410       24
   131          A         509        1
   123          B           2       61
   545          B          19        5
   234          C         439      328
   654          C         765       41

我想做的是能够引入两个新列,salesRankscoreRank,如果它们分别按 salesscore 排序,我可以在其中找到每个类别的项目索引。我可以像这样解决一般情况:

dF <- dF[order(-dF$sales),]
dF$salesRank<-seq.int(nrow(dF))

但这不考虑类别,到目前为止,我只是通过分解数据框来解决这个问题。我想要的结果如下:

   ID       category    sales    score    salesRank    scoreRank
   227          A         109       21         3            2
   131          A         410       24         2            1
   131          A         509        1         1            3
   123          B           2       61         2            1
   545          B          19        5         1            2
   234          C         439      328         2            1
   654          C         765       41         1            2

非常感谢!

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    试试:

    library(dplyr)
    df %>% 
      group_by(category) %>% 
      mutate(salesRank = row_number(desc(sales)),
             scoreRank = row_number(desc(score)))
    

    这给出了:

    #Source: local data frame [7 x 6]
    #Groups: category
    # 
    #   ID category sales score salesRank scoreRank
    #1 227        A   109    21         3         2
    #2 131        A   410    24         2         1
    #3 131        A   509     1         1         3
    #4 123        B     2    61         2         1
    #5 545        B    19     5         1         2
    #6 234        C   439   328         2         1
    #7 654        C   765    41         1         2
    

    来自帮助:

    • row_number():相当于rank(ties.method = "first")
    • min_rank():相当于rank(ties.method = "min")
    • desc():将向量转换为降序排序的格式 订购。

    正如@thelatemail 指出的那样,对于这个特定的数据集,您可能希望使用min_rank() 而不是row_number(),这将更恰当地说明销售额/得分的关系:

    > row_number(c(1,2,2,4))
    #[1] 1 2 3 4
    > min_rank(c(1,2,2,4))
    #[1] 1 2 2 4
    

    【讨论】:

    • 完美 - 谢谢。作为后续问题,是否可以按多个类别进行分组?我也会查看 dplyr 的文档来尝试自己回答这个问题:)
    • 是的。例如,你可以做group_by(ID, category)。见?group_by
    • 您也可以使用rank,这将更恰当地说明销售额/得分的关系。
    • @thelatemail row_number 相当于rank(ties.method = "first")
    • @StevenBeaupré - 这似乎不适合这个示例销售数据 - 例如row_number(c(1,2,2,4)) 返回1,2,3,4?
    【解决方案2】:

    在base R 中使用averank- 是将排名从低到高颠倒到高到低):

    dF$salesRank <- with(dF, ave(-sales, category, FUN=rank) )
    #[1] 3 2 1 2 1 2 1
    dF$scoreRank <- with(dF, ave(-score, category, FUN=rank) )
    #[1] 2 1 3 1 2 1 2
    

    【讨论】:

    • 我很好奇是否有理由更喜欢这个而不是 within(df,{ salesRank = ave(-sales, category, FUN=rank); scoreRank = ave(-score, category, FUN=rank) }) 似乎打字少了。
    • @Frank - 很多,你可以一次完成所有事情,within 非常简洁。尽管我认为这会复制整个数据框,这可能比仅进行逐列计算效率低。这也可能复制整个事情......我不知道。不是我的强项。
    • @Frank ,加上within,你需要做&lt;- 而不是= - 你可以使用transform= 虽然
    • 实际上,我用= 尝试了我运行的代码,它成功了。我认为&lt;- 可以在任何地方工作,= 也可以。不过,关于复制的观点是有道理的。
    • @Frank - 有趣 - within(dF, a="a") 失败,而 within(dF, {a = "a"}) 没有。
    【解决方案3】:

    我只有tapply 的基本 R 解决方案。

    salesRank <- tapply(dat$sales, dat$category, order, decreasing = T)
    scoreRank <- tapply(dat$score, dat$category, order, decreasing = T)
    
    cbind(dat, salesRank = unlist(salesRank), scoreRank= unlist(scoreRank))
    
        ID category sales score salesRank scoreRank
    A1 227        A   109    21         3         2
    A2 131        A   410    24         2         1
    A3 131        A   509     1         1         3
    B1 123        B     2    61         2         1
    B2 545        B    19     5         1         2
    C1 234        C   439   328         2         1
    C2 654        C   765    41         1         2
    

    【讨论】:

    • 这取决于datcategory 排序,对吧?
    • @Frank 是对的 - ave 最好是 unlist(tapply()),因为 tapply 对结果进行排序。首先需要对原始数据进行适当的排序。
    • tapply 是我想到的第一个函数,其实我还是 R 新手,我正在学习。 @Frank 我同意你的观点,非常感谢你的评论,因为乍一看我没有考虑未排序的category 的情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多