如何用R生成指定长度、总和与数值范围的随机向量?
Here's a function that meets all your requirements: fixed vector length, elements within specified range, sum to the target total, and different results on each run:
rand_fixed_vector <- function(n, min_val, max_val, total_sum) { # Check if the total sum is feasible given constraints if (n * min_val > total_sum || n * max_val < total_sum) { stop("Error: Total sum is outside the feasible range for the given parameters.") } # Adjust values to work with non-negative constraints adjusted_total <- total_sum - n * min_val max_adjusted <- max_val - min_val # Generate initial vector of non-negative integers summing to adjusted_total adjusted_vector <- as.vector(rmultinom(1, adjusted_total, rep(1, n))) # Adjust any values that exceed the maximum allowed adjustment while (any(adjusted_vector > max_adjusted)) { # Calculate excess values beyond the max allowed excess <- sum(adjusted_vector[adjusted_vector > max_adjusted] - max_adjusted) # Cap those values at the maximum allowed adjustment adjusted_vector[adjusted_vector > max_adjusted] <- max_adjusted # Find positions where we can distribute the excess available_positions <- which(adjusted_vector < max_adjusted) # Distribute the excess to available positions randomly excess_additions <- as.vector(rmultinom(1, excess, rep(1, length(available_positions)))) adjusted_vector[available_positions] <- adjusted_vector[available_positions] + excess_additions } # Convert back to the original value range final_vector <- adjusted_vector + min_val # Verify all constraints are met (optional, for robustness) stopifnot( length(final_vector) == n, sum(final_vector) == total_sum, all(final_vector >= min_val), all(final_vector <= max_val) ) return(final_vector) }
Why Your Original Function Failed
Your original function produces a vector with length equal to max - min + 1 (since it iterates over min:max), not the fixed length you need. For example, with min=0 and max=100, it returns a vector of length 101 instead of 15. It's counting occurrences of each value in the sample range, not generating a fixed-length vector of values that sum to your target.
Usage Examples
Example 1: Fixed length 15, values 0-100, sum 100
# Generate the vector vec1 <- rand_fixed_vector(n=15, min_val=0, max_val=100, total_sum=100) # Check constraints length(vec1) # 15 sum(vec1) # 100 all(vec1 >= 0 & vec1 <= 100) # TRUE
Example 2: Modified parameters (length 10, values 5-20, sum 100)
vec2 <- rand_fixed_vector(n=10, min_val=5, max_val=20, total_sum=100) sum(vec2) # 100 length(vec2) #10 all(vec2 >=5 & vec2 <=20) # TRUE
Example 3: Edge case (all values at minimum)
vec3 <- rand_fixed_vector(n=5, min_val=3, max_val=10, total_sum=15) # Output will be c(3,3,3,3,3) since 5*3=15
Each time you run the function without setting a seed, you'll get a different valid vector, as it uses R's random number generator.
内容的提问来源于stack exchange,提问作者LOS_2023

