You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让R语言辅助函数同时兼容可变参数(...)与列表输入并保留参数名称

Got it, let's fix this helper function so it properly preserves names whether you pass individual data frames, named arguments, or a named/unnamed list. Here's the revised version that handles all your desired call patterns:

library(janitor)
library(dplyr)
library(stringr)
library(rlang)
library(purrr)

helper_df_compare = function( ..., a_default_arg = "def" ){
  # Step 1: Capture inputs from ... and normalize to a list
  input_list <- list2(...)
  
  # Handle case where user passes a single list (either named or unnamed)
  if (length(input_list) == 1 && is.list(input_list[[1]])) {
    df_list <- input_list[[1]]
  } else {
    df_list <- input_list
  }
  
  # Validate all inputs are data frames
  if (!all(map_lgl(df_list, is.data.frame))) {
    stop("All inputs must be data frames!")
  }
  
  # Step 2: Preserve names from the original call if list is unnamed
  if (is.null(names(df_list))) {
    call_args <- call_args(match.call())
    # Exclude the default argument to avoid interference
    call_args <- call_args[names(call_args) != "a_default_arg"]
    
    df_names <- if (length(call_args) == 1 && is.list(eval(call_args[[1]]))) {
      # For unnamed list inputs, use numeric labels as fallback
      as.character(seq_along(df_list))
    } else {
      # Extract original variable names from the call
      map_chr(call_args, expr_text)
    }
    names(df_list) <- df_names
  }
  
  # Step 3: Run comparison with properly named list
  compare_result <- compare_df_cols(df_list, return = "all") %>%
    mutate_all(~str_replace_all(., c(
      "integer"="int", "numeric"="num", "character"="chr", 
      "factor"="fct", "POSIXct, POSIXt"="POSIXct"
    ))) %>%
    # Mark mismatched columns with !!! prefix
    mutate(column_name = ifelse(match == "mismatch", paste("!!!", column_name), column_name)) %>%
    select(-match) # Remove the redundant match column
  
  return(compare_result)
}

Key Fixes & Explanations:

  • Input Normalization: Uses rlang::list2() to safely capture all ... arguments, including named ones. If you pass a single list (like helper_df_compare(list(people, people2))), it extracts that list directly.
  • Name Preservation: For unnamed inputs (like helper_df_compare(people, people2)), it uses match.call() to pull the original variable names from your code, so the output columns match what you typed.
  • Simplified Comparison: Switches to return = "all" in compare_df_cols() to get all columns in one go, then adds the !!! prefix directly to mismatched columns instead of using rbind().
  • Validation: Adds a quick check to ensure all inputs are data frames, preventing unexpected errors.

Test All Your Call Patterns:

  1. Direct variable inputs:

    helper_df_compare(people, people2, people3)
    

    Output:

    column_name people people2 people3
    1   !!! age     int     num     int
    2     height     num     num     num
    3  lastnames     chr     chr     chr
    4      names     chr     chr     chr
    
  2. Named arguments:

    helper_df_compare(A=people, B=people2, C=people3)
    

    Output:

    column_name A B C
    1   !!! age int num int
    2     height num num num
    3  lastnames chr chr chr
    4      names chr chr chr
    
  3. Named list input:

    helper_df_compare(list("X"=people, "Y"=people2))
    

    Output:

    column_name X Y
    1   !!! age int num
    2     height num num
    3  lastnames chr chr
    4      names chr chr
    
  4. Pre-defined named list:

    database_rnamedlist <- list(people=people, people2=people2, people3=people3)
    helper_df_compare(database_rnamedlist)
    

    Output matches the first test case.

内容的提问来源于stack exchange,提问作者DiegoJArg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 21:42:47