嵌套表格中按列降序并替换为行名的实现报错问题
问题描述
我有一组嵌套表格,希望将行名替换到对应的单元格中,且在替换前按排名对每列进行降序排列。
示例代码如下:
mtX <- apply(mtcars, 2, as.numeric) %>% data.frame(.) rownames(mtX) <- rownames(mtcars) mtNest <- mtX %>% nest_by(vs) %>% ungroup %>% mutate(data = map(data, ~ .x %>% nest(data = -am) %>% mutate(data = map( data, ~ .x %>% nest(data = -gear) %>% mutate(data = map( data, ~ .x %>% mutate(across(., function(x) min_rank(-x))) %>% rownames(data)[order(-.x)] )) )))
执行后出现以下错误:
Error in
mutate():
! Problem while computingdata = map(...).
Caused by error inmutate():
! Problem while computingdata = map(...).
Caused by error inmutate():
! Problem while computingdata = map(...).
Caused by error inmutate():
! Problem while computing..1 = across(., function(x) min_rank(-x)).
Caused by error inacross():
! Must subset columns with a valid subscript vector.
✖ Subscript has the wrong type `tbl_df<
mpg : double
cyl : double
disp: double
hp : double
drat: double
wt : double
qsec: double
carb: double
错误原因
across(., ...)中的.指代整个子数据框,而across要求第一个参数是列选择器(如列名、tidyselect语法),并非完整数据框,这是核心报错原因。- 后续
rownames(data)[order(-.x)]的逻辑混乱,无法正确将排名映射到行名。
修正方案
先将行名转为数据框的一列(避免行名操作的麻烦),再在嵌套层级的最内层,对每个数值列按值降序排序,提取对应行名替换原单元格:
library(tidyverse) # 预处理:将行名转为独立列,方便后续操作 mtX <- mtcars %>% mutate(car = rownames(.)) %>% relocate(car) # 嵌套处理+替换逻辑 mtNest <- mtX %>% nest_by(vs) %>% ungroup() %>% mutate(data = map(data, ~ .x %>% nest(data = -am) %>% mutate(data = map(data, ~ .x %>% nest(data = -gear) %>% mutate(data = map(data, ~ { # 分离数值列与分组列 num_cols <- select(.x, -car, -am, -gear) # 对每个数值列按降序排序,提取对应车型名称 ranked_cars <- map(num_cols, function(col) { .x$car[order(-col)] }) %>% as.data.frame() # 合并分组列与替换后的数值列 bind_cols(select(.x, car, am, gear), ranked_cars) })) )))
逻辑说明
- 预处理阶段把行名转为
car列,规避原生行名在嵌套操作中的丢失问题。 - 最内层嵌套中,先提取所有数值列,对每列按值降序排序后,取出对应位置的车型名称,用这些名称组成新的数值列,最后和分组列(
car/am/gear)合并。
内容的提问来源于stack exchange,提问作者Dollar Tune-bill

