如何将data.table的j槽操作(含函数及参数)作为函数参数传入?
Yes, this is absolutely achievable! The key issue with your original function is that it wasn't properly constructing and evaluating the function calls within data.table's j slot, and it was using the wrong grouping variable. Here's a corrected version of your function that meets your requirements:
Corrected Function
library(data.table) perform_dt_operations <- function(DT, vector_of_variable_names, list_of_functions_with_parameters, vector_for_by){ # Validate input lengths match if(length(vector_of_variable_names) != length(list_of_functions_with_parameters)){ stop("Length of variable names must match length of function-parameter lists") } # Build expressions for each function call in j slot expr_list <- vector("list", length(list_of_functions_with_parameters)) names(expr_list) <- vector_of_variable_names for(i in seq_along(list_of_functions_with_parameters)){ # Extract function name and its parameters fn_name <- names(list_of_functions_with_parameters)[i] args <- list_of_functions_with_parameters[[i]] # Convert character column names to symbols (for flexibility) args <- lapply(args, function(arg) { if(is.character(arg)) as.name(arg) else arg }) # Construct the function call expression expr_list[[i]] <- do.call(call, c(fn_name, args)) } # Execute the data.table operation result <- DT[, eval(expr_list), by = vector_for_by] return(result) }
Key Improvements:
- Proper Expression Construction: We dynamically build each function call (like
sum(x = s, na.rm = TRUE)) as an expression thatdata.tablecan evaluate in its context. - Correct Grouping: Uses your
vector_for_byargument for grouping instead of row names. - Input Validation: Checks that the number of variable names matches the number of function-parameter pairs to avoid mismatches.
- Flexibility: Converts character column names to symbols, so you can pass column names as strings if preferred.
Example Usage:
First, adjust your list_of_functions_with_parameters to use symbols (or strings) for column references (using raw column vectors like s would compute global sums instead of group-wise sums):
DT <- as.data.table(structure(list(peak.grp = c(1L, 2L, 2L, 2L, 2L), s = c(248, 264, 282, 304, 333), height = c(222772.8125, 370112.28125, 426524.03125, 649691.75, 698039)), class = "data.frame", row.names = c(NA, -5L))) # Use quote() for symbols, or pass strings like "s" list_of_functions_with_parameters <- list( sum = list(x = quote(s), na.rm = TRUE), mean = list(x = quote(height), na.rm = TRUE) ) vector_of_variable_names <- c("Sum.s", "Mean.height") vector_for_by <- c("peak.grp")
Now run the function:
Output <- perform_dt_operations(DT, vector_of_variable_names, list_of_functions_with_parameters, vector_for_by) dput(as.data.frame(Output))
Expected Output:
structure(list(peak.grp = c(1, 2), Sum.s = c(248, 1183), Mean.height = c(222772.8125, 536091.765625)), row.names = c(NA, -2L), class = "data.frame")
This matches exactly what you were hoping for!
内容的提问来源于stack exchange,提问作者yasel
相关产品推荐
相关产品推荐

