Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import pandas as pd
- import matplotlib.pyplot as plt
- from scipy import stats
- import math
- VARIANT = 2
- VARIABLE_NAME = "Вага, кг"
- UNIFORM_MIN = 40
- UNIFORM_MAX = 90
- N_OBS = 100
- RANDOM_SEED = 42
- def generate_uniform_data(min_val: float, max_val: float, n: int, seed: int = None) -> np.ndarray:
- rng = np.random.default_rng(seed)
- raw = rng.uniform(min_val, max_val, n)
- rounded = np.round(raw, 0).astype(int)
- return rounded
- def stats_by_formulas(x: np.ndarray) -> dict:
- x = np.asarray(x, dtype=float)
- n = x.size
- x_sorted = np.sort(x)
- x_min = x_sorted[0]
- x_max = x_sorted[-1]
- R = x_max - x_min
- x_mean = x.sum() / n
- if n % 2 == 1:
- median = x_sorted[n // 2]
- else:
- median = 0.5 * (x_sorted[n // 2 - 1] + x_sorted[n // 2])
- values, counts = np.unique(x, return_counts=True)
- mode = values[np.argmax(counts)]
- d = np.mean(np.abs(x - x_mean))
- var_pop = np.mean((x - x_mean) ** 2)
- sigma_pop = np.sqrt(var_pop)
- var_unbiased = var_pop * n / (n - 1)
- sigma_unbiased = np.sqrt(var_unbiased)
- V_R = (R / x_mean) * 100.0
- V_d = (d / x_mean) * 100.0
- V_sigma = (sigma_pop / x_mean) * 100.0
- centered = x - x_mean
- A = (centered ** 3).sum() / (n * (sigma_pop ** 3)) if sigma_pop != 0 else np.nan
- E = (centered ** 4).sum() / (n * (sigma_pop ** 4)) - 3 if sigma_pop != 0 else np.nan
- return {
- "n": n,
- "min": x_min,
- "max": x_max,
- "R": R,
- "mean": x_mean,
- "median": median,
- "mode": mode,
- "d": d,
- "var_pop": var_pop,
- "sigma_pop": sigma_pop,
- "var_unbiased": var_unbiased,
- "sigma_unbiased": sigma_unbiased,
- "V_R": V_R,
- "V_d": V_d,
- "V_sigma": V_sigma,
- "A": A,
- "E": E,
- }
- def stats_by_functions(x: np.ndarray) -> dict:
- x = np.asarray(x, dtype=float)
- n = x.size
- x_min = np.min(x)
- x_max = np.max(x)
- R = x_max - x_min
- x_mean = x.mean()
- median = np.median(x)
- mode = float(pd.Series(x).mode().iloc[0])
- d = np.mean(np.abs(x - x_mean))
- var_pop = np.var(x, ddof=0)
- sigma_pop = np.std(x, ddof=0)
- var_unbiased = np.var(x, ddof=1)
- sigma_unbiased = np.std(x, ddof=1)
- V_R = (R / x_mean) * 100.0
- V_d = (d / x_mean) * 100.0
- V_sigma = (sigma_pop / x_mean) * 100.0
- A = stats.skew(x, bias=False)
- E = stats.kurtosis(x, fisher=True, bias=False)
- return {
- "n": n,
- "min": x_min,
- "max": x_max,
- "R": R,
- "mean": x_mean,
- "median": median,
- "mode": mode,
- "d": d,
- "var_pop": var_pop,
- "sigma_pop": sigma_pop,
- "var_unbiased": var_unbiased,
- "sigma_unbiased": sigma_unbiased,
- "V_R": V_R,
- "V_d": V_d,
- "V_sigma": V_sigma,
- "A": A,
- "E": E,
- }
- def stats_by_addin(x: np.ndarray) -> dict:
- x = np.asarray(x, dtype=float)
- desc = stats.describe(x)
- n = desc.nobs
- x_min, x_max = desc.minmax
- R = x_max - x_min
- x_mean = desc.mean
- var_unbiased = float(desc.variance)
- sigma_unbiased = float(np.sqrt(var_unbiased))
- var_pop = var_unbiased * (n - 1) / n
- sigma_pop = float(np.sqrt(var_pop))
- A = float(desc.skewness)
- E = float(desc.kurtosis)
- median = float(np.median(x))
- mode = float(pd.Series(x).mode().iloc[0])
- d = float(np.mean(np.abs(x - x_mean)))
- V_R = (R / x_mean) * 100.0
- V_d = (d / x_mean) * 100.0
- V_sigma = (sigma_pop / x_mean) * 100.0
- return {
- "n": n,
- "min": x_min,
- "max": x_max,
- "R": R,
- "mean": x_mean,
- "median": median,
- "mode": mode,
- "d": d,
- "var_pop": var_pop,
- "sigma_pop": sigma_pop,
- "var_unbiased": var_unbiased,
- "sigma_unbiased": sigma_unbiased,
- "V_R": V_R,
- "V_d": V_d,
- "V_sigma": V_sigma,
- "A": A,
- "E": E,
- }
- from typing import Tuple
- def check_homogeneity(V_sigma: float) -> str:
- if V_sigma <= 30.0:
- return f"Вибірка однорідна (V_sigma = {V_sigma:.2f}% ≤ 30%)"
- else:
- return f"Вибірка НЕ є однорідною (V_sigma = {V_sigma:.2f}% > 30%)"
- def critical_values_A_E(n: int) -> Tuple[float, float]:
- D_A = 6 * (n - 1) / ((n + 1) * (n + 3))
- D_E = 24 * n * (n - 2) * (n - 3) / (((n + 1) ** 2) * (n + 3) * (n + 5))
- return D_A, D_E
- def check_normality(A: float, E: float, n: int) -> str:
- D_A, D_E = critical_values_A_E(n)
- sigma_A = math.sqrt(D_A)
- sigma_E = math.sqrt(D_E)
- crit_A = 3 * sigma_A
- crit_E = 5 * sigma_E
- cond_A = abs(A) <= crit_A
- cond_E = abs(E) <= crit_E
- lines = []
- lines.append(f"A = {A:.4f}, D(A) = {D_A:.4f}, 3·sqrt(D(A)) = {crit_A:.4f}")
- lines.append(f"E = {E:.4f}, D(E) = {D_E:.4f}, 5·sqrt(D(E)) = {crit_E:.4f}")
- if cond_A and cond_E:
- lines.append("Форма розподілу МОЖЕ вважатися близькою до нормальної (обидві нерівності виконуються).")
- else:
- lines.append("Форма розподілу НЕ є близькою до нормальної (хоча б одна з нерівностей порушена).")
- return "\n".join(lines)
- def sturges_intervals(n: int) -> int:
- if n <= 1:
- return 1
- k = 1 + 3.322 * math.log10(n)
- return int(round(k))
- def build_intervals(x: np.ndarray, k: int) -> np.ndarray:
- x = np.asarray(x, dtype=float)
- x_min = float(np.min(x))
- x_max = float(np.max(x))
- boundaries = np.linspace(x_min, x_max, k + 1)
- boundaries = np.round(boundaries, 1)
- return boundaries
- def grouping_manual(x: np.ndarray, boundaries: np.ndarray) -> pd.DataFrame:
- x = np.asarray(x, dtype=float)
- n = x.size
- k = len(boundaries) - 1
- intervals_left = []
- intervals_right = []
- midpoints = []
- freqs = []
- for i in range(k):
- left = boundaries[i]
- right = boundaries[i + 1]
- if i < k - 1:
- mask = (x >= left) & (x < right)
- else:
- mask = (x >= left) & (x <= right)
- count = int(mask.sum())
- intervals_left.append(left)
- intervals_right.append(right)
- midpoints.append(0.5 * (left + right))
- freqs.append(count)
- freqs = np.array(freqs, dtype=int)
- rel_freq = freqs / n
- cum_freq_pct = np.cumsum(rel_freq) * 100.0
- df = pd.DataFrame({
- "L": intervals_left,
- "U": intervals_right,
- "midpoint": midpoints,
- "n_manual": freqs,
- "p_manual": rel_freq,
- "K_manual_pct": cum_freq_pct,
- })
- return df
- def grouping_addin(x: np.ndarray, boundaries: np.ndarray, df_manual: pd.DataFrame) -> pd.DataFrame:
- x = np.asarray(x, dtype=float)
- k = len(boundaries) - 1
- freqs_addin, _ = np.histogram(x, bins=boundaries)
- n = x.size
- rel_freq_addin = freqs_addin / n
- cum_freq_addin_pct = np.cumsum(rel_freq_addin) * 100.0
- df = df_manual.copy()
- df["n_addin"] = freqs_addin
- df["p_addin"] = rel_freq_addin
- df["K_addin_pct"] = cum_freq_addin_pct
- return df
- def theoretical_uniform_counts(boundaries: np.ndarray, n: int, a: float, b: float) -> np.ndarray:
- probs = (boundaries[1:] - boundaries[:-1]) / (b - a)
- counts = n * probs
- return counts
- def plot_hist_addin(x: np.ndarray, boundaries: np.ndarray):
- plt.figure(figsize=(8, 5))
- plt.hist(x, bins=boundaries, edgecolor="black", alpha=0.7)
- plt.title("Гістограма (аналог статистичної надбудови)")
- plt.xlabel(VARIABLE_NAME)
- plt.ylabel("Частота")
- plt.grid(axis="y", alpha=0.3)
- def plot_hist_polygon_cumulative(df_group_manual: pd.DataFrame):
- fig, ax1 = plt.subplots(figsize=(8, 5))
- L = df_group_manual["L"].values
- U = df_group_manual["U"].values
- mid = df_group_manual["midpoint"].values
- n_manual = df_group_manual["n_manual"].values
- K_manual_pct = df_group_manual["K_manual_pct"].values
- widths = U - L
- ax1.bar(mid, n_manual, width=widths * 0.9, edgecolor="black", alpha=0.6, label="Гістограма (ручне)")
- ax1.plot(mid, n_manual, "o-", label="Полігон")
- ax1.set_xlabel(VARIABLE_NAME)
- ax1.set_ylabel("Частота")
- ax1.set_title("Гістограма та полігон (ручне групування)")
- ax1.grid(alpha=0.3)
- ax2 = ax1.twinx()
- ax2.plot(mid, K_manual_pct, "s-", color="purple", label="Кумулята")
- ax2.set_ylabel("Накопичена частота, %")
- lines1, labels1 = ax1.get_legend_handles_labels()
- lines2, labels2 = ax2.get_legend_handles_labels()
- ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left")
- def plot_empirical_vs_theoretical(df_group_manual: pd.DataFrame, theor_counts: np.ndarray):
- plt.figure(figsize=(8, 5))
- mid = df_group_manual["midpoint"].values
- n_manual = df_group_manual["n_manual"].values
- plt.bar(mid, n_manual, width=(df_group_manual["U"].values - df_group_manual["L"].values) * 0.9,
- edgecolor="black", alpha=0.6, label="Емпірична гістограма")
- plt.plot(mid, theor_counts, "o-", label="Теоретичний розподіл")
- plt.xlabel(VARIABLE_NAME)
- plt.ylabel("Частота")
- plt.title("Емпіричний vs теоретичний розподіл")
- plt.grid(alpha=0.3)
- plt.legend()
- def run_lab(show_plots: bool = True):
- x = generate_uniform_data(UNIFORM_MIN, UNIFORM_MAX, N_OBS, seed=RANDOM_SEED)
- df = pd.DataFrame({"X": x})
- print(f"Практична робота 1-3. Варіант {VARIANT}. Випадкова величина: {VARIABLE_NAME}")
- print(f"Розподіл: рівномірний на [{UNIFORM_MIN}; {UNIFORM_MAX}], n = {N_OBS}")
- print("\nПерші 10 спостережень (округлені значення):")
- print(df.head(10))
- stats_formulas = stats_by_formulas(x)
- stats_funcs = stats_by_functions(x)
- stats_addin = stats_by_addin(x)
- all_keys = list(stats_formulas.keys())
- table = pd.DataFrame({
- "Показник": all_keys,
- "За формулами": [stats_formulas[k] for k in all_keys],
- "Стат. функції": [stats_funcs[k] for k in all_keys],
- "Надбудова": [stats_addin[k] for k in all_keys],
- })
- table.set_index("Показник", inplace=True)
- print("\n=== Показники варіації (три способи) ===")
- print(table)
- homog_text = check_homogeneity(stats_formulas["V_sigma"])
- print("\n=== Однорідність вибірки ===")
- print(homog_text)
- normality_text = check_normality(stats_formulas["A"], stats_formulas["E"], stats_formulas["n"])
- print("\n=== Перевірка близькості до нормального розподілу ===")
- print(normality_text)
- k = sturges_intervals(N_OBS)
- print(f"\nКількість інтервалів (формула Стерджеса): k = {k}")
- boundaries = build_intervals(x, k=k)
- df_group_manual = grouping_manual(x, boundaries)
- df_group = grouping_addin(x, boundaries, df_group_manual)
- print("\n=== Групування даних (ручне + надбудова) ===")
- print(df_group)
- theor_counts = theoretical_uniform_counts(boundaries, N_OBS, UNIFORM_MIN, UNIFORM_MAX)
- print("\nТеоретичні частоти для рівномірного розподілу:")
- print(theor_counts)
- if show_plots:
- plot_hist_addin(x, boundaries)
- plot_hist_polygon_cumulative(df_group_manual)
- plot_empirical_vs_theoretical(df_group_manual, theor_counts)
- plt.show()
- run_lab(show_plots=True)
- print(f"--- РОЗВ'ЯЗАННЯ КОНТРОЛЬНОЇ ЗАДАЧІ ---")
- import numpy as np
- import pandas as pd
- import matplotlib.pyplot as plt
- from scipy import stats
- data = [
- 21, 17, 27, 20, 22, 12, 24, 13, 20, 19, 22, 16, 22,
- 9, 21, 16, 23, 16, 21, 24, 18, 11, 22, 15, 23, 21,
- 10, 15, 18, 15, 21, 14, 15, 18, 22, 15, 17, 19, 17,
- 18, 17, 24, 18, 19, 16, 17, 15, 17, 25, 16
- ]
- x = np.array(data)
- n = len(x)
- print(f"Обсяг вибірки n = {n}")
- unique_elements, counts_elements = np.unique(x, return_counts=True)
- var_series = pd.DataFrame({
- 'Варіанта (xi)': unique_elements,
- 'Частота (ni)': counts_elements
- })
- print("\n1. Варіаційний ряд:")
- print(var_series.to_string(index=False))
- mean_val = np.mean(x)
- median_val = np.median(x)
- mode_result = stats.mode(x, keepdims=True)
- mode_val = mode_result.mode[0]
- mode_count = mode_result.count[0]
- std_dev = np.std(x, ddof=1)
- cv = (std_dev / mean_val) * 100
- print("\n2. Статистичні показники:")
- print(f"{'Середня арифметична (x̄)':<35} {mean_val:.4f}")
- print(f"{'Медіана (Me)':<35} {median_val:.4f}")
- print(f"{'Мода (Mo)':<35} {mode_val} (зустрічається {mode_count} разів)")
- print(f"{'Середнє кв. відхилення (σ або S)':<35} {std_dev:.4f}")
- print(f"{'Коефіцієнт варіації (V)':<35} {cv:.2f} %")
- homogeneity = "ОДНОРІДНА" if cv <= 30 else "НЕОДНОРІДНА"
- print(f"-> Оскільки V = {cv:.2f}%, сукупність є {homogeneity} (поріг 30%).")
- plt.figure(figsize=(10, 6))
- plt.plot(unique_elements, counts_elements, marker='o', linestyle='-', color='b', linewidth=2, markersize=8)
- for i, txt in enumerate(counts_elements):
- plt.annotate(txt, (unique_elements[i], counts_elements[i]),
- textcoords="offset points", xytext=(0,10), ha='center')
- plt.title('Лінійний графік варіаційного ряду (Полігон розподілу)')
- plt.xlabel('Кількість зерен у колосі ($x_i$)')
- plt.ylabel('Частота ($n_i$)')
- plt.xticks(unique_elements)
- plt.grid(True, linestyle='--', alpha=0.7)
- print("\n3. Графік побудовано.")
- plt.show()
Advertisement
Add Comment
Please, Sign In to add comment