我尝试从两列soldier
和superior
创建一个在每个soldier
上方具有较高排名的列表列,以后我可以嵌套以形成长数据,这些列将位于每个上方军衔。因此,对于“ Srg”,值将是“ Lt,Maj,Col,Gen”,对于“ Maj”,值将是“ Col,Gen”。
当前,我发现使用purrr::pmap()
将此for循环应用于整个数据帧的唯一方法是要求我将变量和数据帧名称硬编码到for循环中。
是否可以通过将数据和变量名作为参数的更通用的函数来提取这些等级?
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()
当我尝试使用数据和变量名的参数编写自定义函数get_ranks_above()
时,出现错误消息:
mutate_impl(.data,点)中的错误:
评估错误:元素1的长度为2,而不是1或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
)
)
答案 0 :(得分:0)
我认为做您想做的事的最简单方法是使用有序因子来相互比较等级。在这里,我可以使用parse_factor
来创建有序因子,使用ranks
作为级别并指定应该按照给定的级别进行排序(请注意ranks
已经按顺序排列)。这使得superior
易于确定,我们只需遍历ranks
并检查哪个>
比我们当前的soldier
以及子集ranks
相应。然后我们可以根据需要unnest
并获得我们的长格式数据。
library(tidyverse)
ranks <- c("Srg", "Lt", "Maj", "Col", "Gen")
set.seed(12345)
some_soldiers <- tibble(
soldier = sample(ranks, 5)
)
some_soldiers
#> # A tibble: 5 x 1
#> soldier
#> <chr>
#> 1 Col
#> 2 Gen
#> 3 Maj
#> 4 Lt
#> 5 Srg
some_soldiers %>%
mutate(
soldier = parse_factor(soldier, levels = ranks, ordered = TRUE),
superior = map(soldier, ~ ranks[which(ranks > .x)])
) %>%
unnest()
#> # A tibble: 10 x 2
#> soldier superior
#> <ord> <chr>
#> 1 Col Gen
#> 2 Maj Col
#> 3 Maj Gen
#> 4 Lt Maj
#> 5 Lt Col
#> 6 Lt Gen
#> 7 Srg Lt
#> 8 Srg Maj
#> 9 Srg Col
#> 10 Srg Gen
由reprex package(v0.2.0)于2018-08-21创建。
答案 1 :(得分:0)
我会用有序因素解决这个问题。一旦有了包含所有信息的表,就可以轻松地将其合并到任何数据框。总体思路:
library(dplyr)
library(purrr)
sld_levels <- c("Srg", "Lt", "Maj", "Col", "Gen")
tibble(sld_rank = factor(sld_levels,
levels = sld_levels,
ordered = TRUE)) %>%
mutate(rank_above = map(.x = sld_rank, ~sld_rank[.x < sld_rank]))