基于字典映射列值并按行求和的R可扩展实现方案问询
Scalable R Solution for Mapping Columns with Dictionaries and Row-wise Summation
Problem Overview
You need to map dataframe columns using named dictionaries, compute row-wise sums for each dictionary's mapped values, and optionally combine these sums into a total score. The goal is a scalable approach that avoids inefficient loops.
Solution Code
We'll use vectorized operations (via dplyr) for efficiency and scalability. This approach works for any number of columns or dictionaries.
Step 1: Define the Scalable Function
library(dplyr) compute_score <- function(data, dict, score_name = "score", keep_mapped = FALSE) { # Generate names for mapped columns mapped_col_names <- paste0(names(dict), "_mapped") data %>% # Create mapped columns: multiply each column by its corresponding dict value mutate(across(all_of(names(dict)), ~ .x * dict[[cur_column()]], .names = "{.col}_mapped")) %>% # Calculate row-wise sum of mapped columns to get the score mutate(!!score_name := rowSums(select(., all_of(mapped_col_names)))) %>% # Remove intermediate mapped columns unless specified to keep them { if (!keep_mapped) select(., -all_of(mapped_col_names)) else . } }
Step 2: Apply to Single Dictionary
# Sample data df = data.frame( sex = c(0,0,0,1,0,1,0,1,1,1,0), icu = c(1,1,0,1,0,1,0,1,1,1,1), niv = c(0,1,0,1,0,1,0,0,0,1,0), mv = c(1,0,0,1,1,1,0,0,0,1,0), o2 = c(1,0,0,1,0,1,0,0,0,1,0) ) # Mapping dictionaries dict1 <- list(sex = 0, icu = 2, niv = 1, mv = 3, o2 = 2) dict2 <- list(sex = 3, icu = 4, niv = 2, mv = 6, o2 = 1) # Compute score for dict1 df <- compute_score(df, dict1, score_name = "score_dict1")
Step 3: Apply to Multiple Dictionaries
# Compute score for dict2 df <- compute_score(df, dict2, score_name = "score_dict2") # Calculate total score by summing all individual scores df <- df %>% mutate(total_score = score_dict1 + score_dict2)
Step 4: Batch Processing for N Dictionaries
If you have multiple dictionaries stored in a list, you can loop through them efficiently:
# Store dictionaries in a named list dict_list <- list(dict1 = dict1, dict2 = dict2) # Initialize result dataframe result_df <- df # Apply function to each dictionary for (dict_name in names(dict_list)) { result_df <- compute_score(result_df, dict_list[[dict_name]], score_name = paste0("score_", dict_name)) } # Compute total score across all dictionary scores result_df <- result_df %>% mutate(total_score = rowSums(select(., starts_with("score_"))))
Key Advantages Over Loop-Based Approach
- Vectorized Operations: Avoids slow row-wise loops, making it significantly faster for large datasets.
- Scalability: Works seamlessly with any number of columns (matching dict keys) or dictionaries.
- Flexibility: Option to keep intermediate mapped columns or discard them.
- Readability: Uses modern
dplyrsyntax for clear, maintainable code.
Base R Alternative (No dplyr Required)
If you prefer base R, use this function:
compute_score_base <- function(data, dict, score_name = "score", keep_mapped = FALSE) { # Create mapped columns mapped_cols <- lapply(names(dict), function(col) data[[col]] * dict[[col]]) names(mapped_cols) <- paste0(names(dict), "_mapped") # Combine mapped columns with original data data <- cbind(data, mapped_cols) # Calculate row-wise sum for score data[[score_name]] <- rowSums(data[, names(mapped_cols)]) # Remove mapped columns if requested if (!keep_mapped) { data <- data[, !names(data) %in% names(mapped_cols)] } return(data) }
Content of the question originates from Stack Exchange, question author Henrique
相关产品推荐
相关产品推荐

