【问题标题】:mutate by group in R在R中按组变异
【发布时间】:2018-12-13 06:51:27
【问题描述】:

我有一个包含以下列的数据:

    Date         CID      FID        rank  
    31/01/17     abc0001  rx180x01    0
    31/01/17     abc0001  rx180x02    0
    31/01/17     abc0001  rx180x03    2
    28/02/17     abc0001  rx180x32    1
    28/02/17     abc0001  rx180x31    0

每个 CID 都有一些唯一的 FID 映射到它,并且这些 FID 具有一些等级。我需要创建 2 个新列 finalrank 和 finalFID。

最终排名是每个 CID 在每个日期的最大排名。即对于 CID abc0001 ,在日期 31/01/17 中,finalrank 将为 2。此逻辑将应用于所有唯一的 CID-日期组合。

FinalFID 是在日期中对 CID 具有特定 finalrank 值的 FID。例如,在日期 31/01/17 中,对于 CID abc0001 ,具有最大排名的 FID 是 rx180x03

所以我的结果应该是这样的:

    Date         CID      FID        rank  finalrank finalFID
    31/01/17     abc0001  rx180x01    0    2         rx180x03
    31/01/17     abc0001  rx180x02    0    2         rx180x03
    31/01/17     abc0001  rx180x03    2    2         rx180x03
    28/02/17     abc0001  rx180x32    1    1         rx180x32
    28/02/17     abc0001  rx180x31    0    1         rx180x32

我编写了一个看起来很优雅的代码,但它不适用于非常大的数据。我正在处理的那个有5,000,000。当我在 R 中运行它时,它显示为如此庞大的数据帧运行了其他任何东西。

       data          = dplyr::group_by(data,CID,date)
       data          = arrange(data,CID,date)
       data          = dplyr::mutate(data, finalrank =max(rank))

       # Id FID of maximum rank
       data   = dplyr::mutate(data, match = FID[match(finalrank ,rank)])

【问题讨论】:

    标签: r window-functions dplyr


    【解决方案1】:
    dat%>%
       group_by(Date,CID)%>%
       mutate(finalrank=max(rank),finalFID=FID[which.max(rank)])
    # A tibble: 5 x 6
    # Groups:   Date, CID [2]
      Date     CID     FID       rank finalrank finalFID
      <fct>    <fct>   <fct>    <int>     <dbl> <fct>   
    1 31/01/17 abc0001 rx180x01     0         2 rx180x03
    2 31/01/17 abc0001 rx180x02     0         2 rx180x03
    3 31/01/17 abc0001 rx180x03     2         2 rx180x03
    4 28/02/17 abc0001 rx180x32     1         1 rx180x32
    5 28/02/17 abc0001 rx180x31     0         1 rx180x32
    

    使用data.table

    library(data.table)
    setDT(dat)[,c("finalrank","finalFID"):=.(max(rank),FID[which.max(rank)]),by=.(Date,CID)]
    dat 
           Date     CID      FID rank finalrank finalFID
    1: 31/01/17 abc0001 rx180x01    0         2 rx180x03
    2: 31/01/17 abc0001 rx180x02    0         2 rx180x03
    3: 31/01/17 abc0001 rx180x03    2         2 rx180x03
    4: 28/02/17 abc0001 rx180x32    1         1 rx180x32
    5: 28/02/17 abc0001 rx180x31    0         1 rx180x32
    

    【讨论】:

    • 谢谢。但它仍在运行,兄弟
    • 那么您需要使用data.table 而不是tidyverse。看来你有一个大数据集
    • @DomJo 你是说这个例子还在运行还是你的整个数据集还在运行?
    • @DomJo 用于数据表解决方案.. 类似:library(data.table);setDT(dat)[,c("finalrank","finalFID"):=.(max(rank),FID[which.max(rank)]),by=.(Date,CID)];dat
    • 嗨。这似乎工作得非常快。你为什么不一开始就写这个作为答案?
    【解决方案2】:

    使用dplyr 的方法预计会更快,是通过arranging 上的Date, CID, rank 数据,然后采用last。解决方案如下:

    library(dplyr)
    
    df %>% mutate(Date = as.POSIXct(Date,format = "%d/%m/%y")) %>%
      group_by(Date, CID) %>%
      arrange(Date, CID, rank) %>%
      mutate(finalrank = last(rank), finalFID=last(FID)) %>%
      as.data.frame()
    
    #         Date     CID      FID rank finalrank finalFID
    # 1 2017-01-31 abc0001 rx180x01    0         2 rx180x03
    # 2 2017-01-31 abc0001 rx180x02    0         2 rx180x03
    # 3 2017-01-31 abc0001 rx180x03    2         2 rx180x03
    # 4 2017-02-28 abc0001 rx180x31    0         1 rx180x32
    # 5 2017-02-28 abc0001 rx180x32    1         1 rx180x32
    

    已编辑:澄清@Onyambu 的疑问,即如果最后一行没有排名的最大值,那么解决方案也有效。

    df$rank[1] <- 3
    
    df %>% mutate(Date = as.POSIXct(Date,format = "%d/%m/%y")) %>%
      group_by(Date, CID) %>%
      arrange(Date, CID, rank) %>%
      mutate(finalrank = last(rank), finalFID=last(FID)) %>%
      as.data.frame()
    
    
    #        Date     CID      FID rank finalrank finalFID
    # 1 2017-01-31 abc0001 rx180x02    0         3 rx180x01
    # 2 2017-01-31 abc0001 rx180x03    2         3 rx180x01
    # 3 2017-01-31 abc0001 rx180x01    3         3 rx180x01
    # 4 2017-02-28 abc0001 rx180x31    0         1 rx180x32
    # 5 2017-02-28 abc0001 rx180x32    1         1 rx180x32
    

    数据:

    df <- read.table(text=
    "Date         CID      FID        rank  
    31/01/17     abc0001  rx180x01    0
    31/01/17     abc0001  rx180x02    0
    31/01/17     abc0001  rx180x03    2
    28/02/17     abc0001  rx180x32    1
    28/02/17     abc0001  rx180x31    0",
    header = TRUE,  stringsAsFactors = FALSE)
    

    【讨论】:

    • 这在具有最大排名的 FID 不是最大/最后的情况下不起作用
    • @Onyambu 它会起作用的。只需将第一行的等级更改为 3 并运行解决方案。你会看到正确的结果。
    • 我明白了,我明白你的意思
    猜你喜欢
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 2021-06-21
    • 2021-06-17
    相关资源
    最近更新 更多