在R中按组进行变异

6

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

    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,每个CID都有一些排名。我需要创建两个新列finalrank和finalFID。
finalrank是每个日期中每个CID的最大排名。例如,对于CID abc0001,在日期31/01/17中,finalrank将为2。这个逻辑将应用于所有唯一的CID-日期组合。
FinalFID是具有特定finalrank值的CID在日期中的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

我写了一段代码,看起来很优雅,也很好,但是对于非常大的数据却无法运行。我正在处理的数据有500万条。当我在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)])
2个回答

8
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。看起来你有一个大数据集。 - Onyambu
@DomJo,你是说这个例子还在运行,还是你的整个数据集还在运行? - Onyambu
@DomJo 关于datatable解决方案.. 大致如下: library(data.table);setDT(dat)[,c("finalrank","finalFID"):=.(max(rank),FID[which.max(rank)]),by=.(Date,CID)];dat - Onyambu
只需修改答案以显示setDT解决方案,不是吗? 它仍然显示旧的。 你能分享一些关于setDT的链接吗? “:=.”是什么意思? - Dom Jo
在您的Rconsole上,输入?data.table或者您可以点击这里,并且点击您想要了解的函数,包括:= - Onyambu
显示剩余6条评论

3

使用 dplyr 的一种更快的方法是通过对数据进行 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
@Onyambu 这会起作用的。只需将第一行的排名更改为3并运行解决方案。您将看到正确的结果。 - MKR
1
我明白了,我明白你的意思。 - Onyambu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接