生成具有指定均值、标准差、最小值和最大值的随机数
Great question! The Maxwell distribution you initially tried won't work here—with your loc=1.5 and scale=3.1, its theoretical mean is around 6.45 (way below your target 9.87), and it has an unbounded right tail that would spit out values far exceeding 35. Below are three actionable approaches to generate your 10,000-point dataset that meets all your requirements:
1. Truncated Normal Distribution (Most Accurate)
The truncated normal distribution is perfect here because we can mathematically adjust its underlying parameters to match your target mean, standard deviation, and bounds. We'll use numerical optimization to find the right μ and σ for the untruncated normal distribution, such that when we truncate it to [1.5, 35], we get your desired stats.
Here's how to implement it with scipy:
import numpy as np from scipy.stats import truncnorm from scipy.optimize import root # Target parameters target_min = 1.5 target_max = 35 target_mean = 9.87 target_std = 3.1 # Define function to calculate difference between truncated stats and targets def params_error(x): mu, sigma = x a = (target_min - mu) / sigma b = (target_max - mu) / sigma # Calculate truncated mean and std trunc_mean = truncnorm.mean(a, b, loc=mu, scale=sigma) trunc_std = truncnorm.std(a, b, loc=mu, scale=sigma) return [trunc_mean - target_mean, trunc_std - target_std] # Solve for optimal mu and sigma initial_guess = [target_mean, target_std] solution = root(params_error, initial_guess) optimal_mu, optimal_sigma = solution.x # Generate the dataset a_opt = (target_min - optimal_mu) / optimal_sigma b_opt = (target_max - optimal_mu) / optimal_sigma dataset = truncnorm.rvs(a_opt, b_opt, loc=optimal_mu, scale=optimal_sigma, size=10000) # Verify stats (should be very close to targets) print(f"Mean: {np.mean(dataset):.2f}, Std Dev: {np.std(dataset):.2f}") print(f"Min: {np.min(dataset):.2f}, Max: {np.max(dataset):.2f}")
This method gives you a dataset that closely matches all your requirements, with a smooth, bell-shaped distribution (adjustable if you prefer a right-skewed shape—see next approach).
2. Truncated Gamma Distribution (Right-Skewed Alternative)
If you want a right-skewed distribution (more similar to Maxwell), a truncated Gamma distribution works well. We'll use the same optimization approach to find the shape and scale parameters that fit your targets:
import numpy as np from scipy.stats import gamma from scipy.optimize import root # Target parameters target_min = 1.5 target_max = 35 target_mean = 9.87 target_std = 3.1 def gamma_params_error(x): shape, scale = x # Calculate truncated mean and std lower_cdf = gamma.cdf(target_min, a=shape, scale=scale) upper_cdf = gamma.cdf(target_max, a=shape, scale=scale) trunc_mean = (gamma.expect(lambda x: x, a=shape, scale=scale, lb=target_min, ub=target_max) / (upper_cdf - lower_cdf)) trunc_var = (gamma.expect(lambda x: x**2, a=shape, scale=scale, lb=target_min, ub=target_max) / (upper_cdf - lower_cdf)) - trunc_mean**2 trunc_std = np.sqrt(trunc_var) return [trunc_mean - target_mean, trunc_std - target_std] # Solve for optimal shape and scale initial_guess = [5, 2] # Starting guess for right-skewed shape solution = root(gamma_params_error, initial_guess) optimal_shape, optimal_scale = solution.x # Generate truncated Gamma samples dataset = [] while len(dataset) < 10000: sample = gamma.rvs(a=optimal_shape, scale=optimal_scale) if target_min <= sample <= target_max: dataset.append(sample) dataset = np.array(dataset) # Verify stats print(f"Mean: {np.mean(dataset):.2f}, Std Dev: {np.std(dataset):.2f}") print(f"Min: {np.min(dataset):.2f}, Max: {np.max(dataset):.2f}")
This gives you a right-skewed distribution like Maxwell, but bounded and tuned to your exact mean/std.
3. Heuristic Adjustment (Quick & Simple)
If you don't need perfect mathematical precision, you can generate an initial dataset, truncate it to your bounds, then linearly adjust it to match your target mean and std:
import numpy as np from scipy.stats import maxwell # Target parameters target_min = 1.5 target_max = 35 target_mean = 9.87 target_std = 3.1 # Generate initial Maxwell samples (oversample to account for truncation) initial_data = maxwell.rvs(loc=1.5, scale=5, size=15000) # Truncate to bounds truncated_data = initial_data[(initial_data >= 1.5) & (initial_data <= 35)] # Keep only 10000 points truncated_data = truncated_data[:10000] # Calculate current stats curr_mean = np.mean(truncated_data) curr_std = np.std(truncated_data) # Linearly adjust to match target stats adjusted_data = (truncated_data - curr_mean) * (target_std / curr_std) + target_mean # Re-truncate any values that went out of bounds after adjustment adjusted_data = np.clip(adjusted_data, target_min, target_max) # Verify stats print(f"Mean: {np.mean(adjusted_data):.2f}, Std Dev: {np.std(adjusted_data):.2f}") print(f"Min: {np.min(adjusted_data):.2f}, Max: {np.max(adjusted_data):.2f}")
This method is fast and retains the Maxwell-like shape, though the final stats might be slightly off (you can iterate the adjustment step if needed).
内容的提问来源于stack exchange,提问作者Joe Buckley

