如何基于因子变量的子集创建标准化排名列?
How to create a normalised rank column based on subset of factor variable?
数据框样本:
df <- structure(list(Rank = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Year = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("2001", "2003", "2005", "2007", "2009", "2011", "2013", "2015", "2017"), class = "factor")), .Names = c("Rank", "Year"), row.names = c(NA, -44L), class = c("tbl_df", "tbl", "data.frame"))
我的数据框中有一个 "Rank" 向量,范围从 1 到 x,具体取决于 "Year" 中的因子值。我希望能够根据年份值对排名进行标准化,并将其放入新列中。
到目前为止,我正在使用此自定义函数在 0 和 1 之间进行归一化:
range01 <- function(x){(x-min(x))/(max(x)-min(x))}
我创建了一个用 NA 填充的新列。
df$normrank <- NA
然后我尝试生成 2001 年的规范化排名,但是这会在子集因子值的每一行中创建新规范化排名向量的副本,而不是将行中的规范化值与相应的旧匹配值。
df$normrank[which(df$Year==2001)] <- range01(subset(df, Year == 2001, select=Rank))
我不知道如何解决这个问题,希望得到任何帮助 - 可能使用另一个自定义函数?
使用dplyr
的一个解决方案可以基于Year
列上的group_by
,然后应用归一化因子计算normrank
。
df %>% group_by(Year) %>%
mutate(normrank = (Rank - min(Rank)) / (max(Rank)+min(Rank)) )
# # Groups: Year [3]
# Rank Year normrank
# <dbl> <fctr> <dbl>
# 1 1.00 2001 0
# 2 2.00 2001 0.0556
# 3 3.00 2001 0.111
# 4 4.00 2001 0.167
# 5 5.00 2001 0.222
# 6 6.00 2001 0.278
# 7 7.00 2001 0.333
# 8 8.00 2001 0.389
# 9 9.00 2001 0.444
# 10 10.0 2001 0.500
# # ... with 34 more rows
现在数据已准备好 filter
Year
。
数据框样本:
df <- structure(list(Rank = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Year = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("2001", "2003", "2005", "2007", "2009", "2011", "2013", "2015", "2017"), class = "factor")), .Names = c("Rank", "Year"), row.names = c(NA, -44L), class = c("tbl_df", "tbl", "data.frame"))
我的数据框中有一个 "Rank" 向量,范围从 1 到 x,具体取决于 "Year" 中的因子值。我希望能够根据年份值对排名进行标准化,并将其放入新列中。
到目前为止,我正在使用此自定义函数在 0 和 1 之间进行归一化:
range01 <- function(x){(x-min(x))/(max(x)-min(x))}
我创建了一个用 NA 填充的新列。
df$normrank <- NA
然后我尝试生成 2001 年的规范化排名,但是这会在子集因子值的每一行中创建新规范化排名向量的副本,而不是将行中的规范化值与相应的旧匹配值。
df$normrank[which(df$Year==2001)] <- range01(subset(df, Year == 2001, select=Rank))
我不知道如何解决这个问题,希望得到任何帮助 - 可能使用另一个自定义函数?
使用dplyr
的一个解决方案可以基于Year
列上的group_by
,然后应用归一化因子计算normrank
。
df %>% group_by(Year) %>%
mutate(normrank = (Rank - min(Rank)) / (max(Rank)+min(Rank)) )
# # Groups: Year [3]
# Rank Year normrank
# <dbl> <fctr> <dbl>
# 1 1.00 2001 0
# 2 2.00 2001 0.0556
# 3 3.00 2001 0.111
# 4 4.00 2001 0.167
# 5 5.00 2001 0.222
# 6 6.00 2001 0.278
# 7 7.00 2001 0.333
# 8 8.00 2001 0.389
# 9 9.00 2001 0.444
# 10 10.0 2001 0.500
# # ... with 34 more rows
现在数据已准备好 filter
Year
。