使用等级顺序计算 R 中的死亡率数据
Using rank order to calculate death rate data in R
我想对每个个人 ID 中的每个小时值进行排名。彼此相等的小时值将是相同的排名。我试图用 data.table 中的行计数函数 (.N) 来做到这一点。我希望这会奏效,但我想不通。
这是一个可重现的例子,如果您对我的问题有任何疑问,请告诉我。
library(data.table)
dt <- data.table(hours=c(100, 72, 48, 98, 87, 75, 98, 75, 52, 48, 100, 98, 87, 35, 48, 75, 92, 100, 75, 48),
id=rep(1:4, each=5, 1))
dt <- dt[, list(.(hours <= hours), .N), list(hours, id)]
期望的输出
任何帮助将不胜感激。
[更新]:
这个问题的一个附带目标是获取不同 "id" 组随时间变化的死亡率。这是通过以下代码完成的,我还包括了一个很酷的图表来显示这种关系随时间的变化。该代码改编自 akrun 使用 data.table 包中的 frankv() 函数提供的答案。
library(ggplot2)
dt <- dt[,list(tot=.N, hours=hours), list(id)]
dt[, rank.total := frankv(hours, ties.method = 'max'), id]
dt[, death:= rank.total/tot, id]
dt[, alive:= 1-death, id]
ggplot(dt, aes(x=hours, y=alive, color=as.factor(id))) +
geom_line() +
geom_point() +
theme_minimal() +
labs(x="Hours", y="% Alive", title= "Death rate over time", color="Group")
您可以将 hours
转换为 factor
,然后将 integer
转换为 integer
,这将根据您想要的输出自动正确处理关系。
library(data.table)
dt[, rank.total := as.integer(factor(hours)), id]
dt
# hours id rank.total
# 1: 100 1 5
# 2: 72 1 2
# 3: 48 1 1
# 4: 98 1 4
# 5: 87 1 3
# 6: 75 2 3
# 7: 98 2 4
# 8: 75 2 3
# 9: 52 2 2
#10: 48 2 1
#11: 100 3 5
#12: 98 3 4
#13: 87 3 3
#14: 35 3 1
#15: 48 3 2
#16: 75 4 2
#17: 92 4 3
#18: 100 4 4
#19: 75 4 2
#20: 48 4 1
你也可以在 dplyr
和 base R
中做同样的事情
library(dplyr)
dt %>% group_by(id) %>% mutate(total.rank = as.integer(factor(hours)))
和
dt$total.rank <- with(dt, ave(hours, id, FUN = function(x) as.integer(factor(x))))
我们可以使用match
library(data.table)
dt[, rank.total := match(hours, unique(hours)), id]
如果我们需要倒序,使用frank
dt[, rank.total := frank(-hours, ties.method = 'dense'), id]
dt
# hours id rank.total
# 1: 100 1 1
# 2: 72 1 4
# 3: 48 1 5
# 4: 98 1 2
# 5: 87 1 3
# 6: 75 2 2
# 7: 98 2 1
# 8: 75 2 2
# 9: 52 2 3
#10: 48 2 4
#11: 100 3 1
#12: 98 3 2
#13: 87 3 3
#14: 35 3 5
#15: 48 3 4
#16: 75 4 3
#17: 92 4 2
#18: 100 4 1
#19: 75 4 3
#20: 48 4 4
改变它通常的顺序
dt[, rank.total := frank(hours, ties.method = 'dense'), id]
dt
# hours id rank.total
# 1: 100 1 5
# 2: 72 1 2
# 3: 48 1 1
# 4: 98 1 4
# 5: 87 1 3
# 6: 75 2 3
# 7: 98 2 4
# 8: 75 2 3
# 9: 52 2 2
#10: 48 2 1
#11: 100 3 5
#12: 98 3 4
#13: 87 3 3
#14: 35 3 1
#15: 48 3 2
#16: 75 4 2
#17: 92 4 3
#18: 100 4 4
#19: 75 4 2
#20: 48 4 1
或 match
dt[, rank.total := match(hours, rev(sort(unique(hours)))), id]
我想对每个个人 ID 中的每个小时值进行排名。彼此相等的小时值将是相同的排名。我试图用 data.table 中的行计数函数 (.N) 来做到这一点。我希望这会奏效,但我想不通。
这是一个可重现的例子,如果您对我的问题有任何疑问,请告诉我。
library(data.table)
dt <- data.table(hours=c(100, 72, 48, 98, 87, 75, 98, 75, 52, 48, 100, 98, 87, 35, 48, 75, 92, 100, 75, 48),
id=rep(1:4, each=5, 1))
dt <- dt[, list(.(hours <= hours), .N), list(hours, id)]
期望的输出
任何帮助将不胜感激。
[更新]:
这个问题的一个附带目标是获取不同 "id" 组随时间变化的死亡率。这是通过以下代码完成的,我还包括了一个很酷的图表来显示这种关系随时间的变化。该代码改编自 akrun 使用 data.table 包中的 frankv() 函数提供的答案。
library(ggplot2)
dt <- dt[,list(tot=.N, hours=hours), list(id)]
dt[, rank.total := frankv(hours, ties.method = 'max'), id]
dt[, death:= rank.total/tot, id]
dt[, alive:= 1-death, id]
ggplot(dt, aes(x=hours, y=alive, color=as.factor(id))) +
geom_line() +
geom_point() +
theme_minimal() +
labs(x="Hours", y="% Alive", title= "Death rate over time", color="Group")
您可以将 hours
转换为 factor
,然后将 integer
转换为 integer
,这将根据您想要的输出自动正确处理关系。
library(data.table)
dt[, rank.total := as.integer(factor(hours)), id]
dt
# hours id rank.total
# 1: 100 1 5
# 2: 72 1 2
# 3: 48 1 1
# 4: 98 1 4
# 5: 87 1 3
# 6: 75 2 3
# 7: 98 2 4
# 8: 75 2 3
# 9: 52 2 2
#10: 48 2 1
#11: 100 3 5
#12: 98 3 4
#13: 87 3 3
#14: 35 3 1
#15: 48 3 2
#16: 75 4 2
#17: 92 4 3
#18: 100 4 4
#19: 75 4 2
#20: 48 4 1
你也可以在 dplyr
和 base R
library(dplyr)
dt %>% group_by(id) %>% mutate(total.rank = as.integer(factor(hours)))
和
dt$total.rank <- with(dt, ave(hours, id, FUN = function(x) as.integer(factor(x))))
我们可以使用match
library(data.table)
dt[, rank.total := match(hours, unique(hours)), id]
如果我们需要倒序,使用frank
dt[, rank.total := frank(-hours, ties.method = 'dense'), id]
dt
# hours id rank.total
# 1: 100 1 1
# 2: 72 1 4
# 3: 48 1 5
# 4: 98 1 2
# 5: 87 1 3
# 6: 75 2 2
# 7: 98 2 1
# 8: 75 2 2
# 9: 52 2 3
#10: 48 2 4
#11: 100 3 1
#12: 98 3 2
#13: 87 3 3
#14: 35 3 5
#15: 48 3 4
#16: 75 4 3
#17: 92 4 2
#18: 100 4 1
#19: 75 4 3
#20: 48 4 4
改变它通常的顺序
dt[, rank.total := frank(hours, ties.method = 'dense'), id]
dt
# hours id rank.total
# 1: 100 1 5
# 2: 72 1 2
# 3: 48 1 1
# 4: 98 1 4
# 5: 87 1 3
# 6: 75 2 3
# 7: 98 2 4
# 8: 75 2 3
# 9: 52 2 2
#10: 48 2 1
#11: 100 3 5
#12: 98 3 4
#13: 87 3 3
#14: 35 3 1
#15: 48 3 2
#16: 75 4 2
#17: 92 4 3
#18: 100 4 4
#19: 75 4 2
#20: 48 4 1
或 match
dt[, rank.total := match(hours, rev(sort(unique(hours)))), id]