在 R 中按组变异
mutate by group in R
我有一个包含以下列的数据:
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,在日期 2017 年 1 月 31 日,最终排名将为 2。此逻辑将应用于所有唯一的 CID-日期组合。
FinalFID 是 date.For 中的 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)])
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
一种使用 dplyr
的方法预计会更快,即通过 Date, CID, rank
上的 arranging
数据,然后采用 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)
我有一个包含以下列的数据:
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,在日期 2017 年 1 月 31 日,最终排名将为 2。此逻辑将应用于所有唯一的 CID-日期组合。
FinalFID 是 date.For 中的 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)])
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
一种使用 dplyr
的方法预计会更快,即通过 Date, CID, rank
上的 arranging
数据,然后采用 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)