如何基于特征表行高效创建指定列格式的空Data Frame?
简洁生成指定结构的空数据框方案
需求说明
有一个描述性辅助表,其中:
varCat:变量类别rept:该类别需要重复生成的列数form:指定对应列的数据格式(text为字符型,num为数值型)
辅助表代码:
library(dplyr) library(tidyr) library(purrr) library(stringr) descr <- tibble( varCat = c("a", "b"), rept = c(1, 3), form = c("text", "num") )
需要生成的目标空数据框:
#> # A tibble: 0 × 4 #> # … with 4 variables: a <chr>, b_1 <dbl>, b_2 <dbl>, b_3 <dbl>
实现要求
- 列名规则:
rept等于1时,列名直接用varCat;rept大于1时,生成带_1、_2等后缀的序列列名 - 列数据类型需匹配
descr$form指定的类型
原繁琐实现(参考)
# Step 1: tmp <- descr %>% uncount(rept, .id = "rept") %>% group_by(varCat) %>% mutate( n = n(), var = case_when( n > 1 ~ paste0(varCat, "_", rept), TRUE ~ varCat ) ) %>% ungroup %>% select(var, form) c <- tmp$var d <- matrix(ncol = length(c), nrow = 0) %>% as_tibble(.name_repair = "unique") %>% set_names(c) # Step 2: for (i in colnames(d)) { for (j in seq_along(tmp$var)) { if (tmp$var[j] == i & tmp$form[j] == "text") d[i] <- as.character(d[i]) else if (tmp$var[j] == i & tmp$form[j] == "num") d[i] <- as.numeric(d[i]) } }
简洁实现方案
利用tidyverse的映射函数一次性完成列名生成和类型匹配:
library(tidyverse) # 生成列名与对应类型的映射列表 col_spec <- descr %>% mutate( # 生成每个类别对应的列名向量 vars = map2(varCat, rept, ~if (.y == 1) .x else str_c(.x, "_", 1:.y)), # 生成对应类型的空向量 type = map(form, ~if (.x == "text") character() else numeric()) ) %>% unnest(c(vars, type)) %>% deframe() # 构建空tibble d <- tibble(!!!col_spec) # 查看结果 d #> # A tibble: 0 × 4 #> # … with 4 variables: a <chr>, b_1 <dbl>, b_2 <dbl>, b_3 <dbl>
代码解释
map2(varCat, rept, ...):针对每个变量类别,根据重复次数生成对应的列名序列map(form, ...):根据格式类型生成对应类型的空向量(字符型或数值型)unnest:将嵌套的列名和类型向量展开为行deframe:将两列转换为列名-类型的命名列表tibble(!!!col_spec):通过非标准评估将命名列表转换为指定结构的空tibble,自动匹配列类型
内容的提问来源于stack exchange,提问作者Turtle
相关产品推荐
相关产品推荐

