From two columns soldier and superior I am trying to create a list column of the superior ranks above each soldier that I can later unnest to form long data will all ranks above each soldier's rank. So for "Srg" the values would be "Lt, Maj, Col, Gen", and for "Maj" the value would be "Col, Gen".
Currently the only way I've found to apply this for-loop to the entire dataframe using purrr::pmap() requires me to hardcode in variable and dataframe names into the for-loop.
Is there a way I could extract these ranks in a more generalizable function that took data and variable names as arguments?
library(dplyr)
library(tidyr)
library(purrr)
# Create test data
data <-
dplyr::tibble(
soldier = c("Srg", "Lt", "Maj", "Col", "Gen"),
superior = c("Lt", "Maj", "Col", "Gen", NA)
)
# Define custom function
get_ranks_above <- function(id, max_steps = 5){
ranks_above <- vector("list", length = max_steps)
for (i in 1:max_steps) {
ranks_above[[i]] <-
data.frame(
superior_list = data$superior[data$soldier == id]
)
id <- ranks_above[[i]]$superior_list
}
do.call(rbind, ranks_above)
}
# Apply custom function
data_ranked <-
data %>%
mutate(
ranks_above = pmap(
list(id = soldier),
get_ranks_above
)
)
# Unnest list column and add numeric ranks
data_ranked %>%
unnest(ranks_above) %>%
drop_na() %>%
group_by(soldier) %>%
mutate(rank_from_top = seq(n(),1)) %>%
ungroup()
When I try to write the custom function get_ranks_above() with arguments for data and variable names I get an error message:
Error in mutate_impl(.data, dots) :
Evaluation error: Element 1 has length 2, not 1 or 5..
get_ranks_above <- function(data, id = soldier, lower_rank = data$soldier, upper_rank = data$superior, max_steps = 5){
ranks_above <- vector("list", length = max_steps)
for (i in 1:max_steps) {
ranks_above[[i]] <-
data.frame(
superior_list = upper_rank[lower_rank == id]
)
id <- ranks_above[[i]]$superior_list
}
do.call(rbind, ranks_above)
}
data_ranked <-
data %>%
mutate(
ranks_above = pmap(
list(
data = data,
id = soldier,
lower_rank = data$soldier,
upper_rank = data$superior,
max_steps = 5
),
get_ranks_above
)
)