lab5
/
calculator.py
393 строки · 17.2 Кб
1import matplotlib.pyplot as plt2from prettytable import PrettyTable3
4from math import ceil5
6
7class Calculator:8def __init__(self):9self._sample_mean = """10___
11x_в = n^(-1) * sum(x_i * n_i)
12"""
13self._dispersion = """14_____ ___
15D_в = x^2_в - (x_в)^2
16"""
17self._standard_deviation = """18b = (D_в)^(0.5)
19"""
20self._unbiased_assessment = """21S = n/(n - 1) * D_в
22"""
23
24# ------------математичесие методы---------------25def get_frequencies(self, data: list[float]) -> list[int]:26"""27Получить частоты
28:param data: статистические данные
29:return: частоты
30"""
31count = dict()32for i in data:33count[i] = count.get(i, 0) + 134freq = []35for i in sorted(count.keys()):36freq.append(count[i])37return freq38
39def get_relative_frequencies(self, data: list[float]) -> list[float]:40"""41Получить относительные частоты
42:param data: статистические данные
43:return: относительные частоты
44"""
45freq = self.get_frequencies(data)46return [i / sum(freq) for i in freq]47
48def sample_mean(self, variation_series: list[float], frequencies: list[int]) -> float:49"""50Получить выборочное среднее
51:param variation_series: вариационный ряд
52:param frequencies: ряд частот
53:return: выборочное среднее
54"""
55return (1 / sum(frequencies)) * sum(x * n for x, n in zip(variation_series, frequencies))56
57def dispersion(self, variation_series: list[float], frequencies: list[int]) -> float:58"""59Получить дисперсию
60:param variation_series: выриационный ряд
61:param frequencies: ряд частот
62:return: дисперсия
63"""
64x = self.sample_mean(variation_series, frequencies)65x_2 = self.sample_mean([i ** 2 for i in variation_series], frequencies)66return x_2 - x ** 267
68def standard_deviation(self, variation_series: list[float], frequencies: list[int]) -> float:69"""70Получить квадратичное отклонение
71:param variation_series: выриационный ряд
72:param frequencies: ряд частот
73:return: квадратичное отклоненение
74"""
75return self.dispersion(variation_series, frequencies) ** 0.576
77def unbiased_assessment(self, variation_series: list[float], frequencies: list[int]) -> float:78"""79Получить несмещенную оценку
80:param variation_series: выриационный ряд
81:param frequencies: ряд частот
82:return: несмещенная оценка
83"""
84n = sum(frequencies)85return n / (n - 1) * self.dispersion(variation_series, frequencies)86
87def get_intervals(self, data: list[float], interval_number: int) -> list[list[int]]:88var = self.solveB1(data)89mx = max(var)90mn = min(var)91step = (mx - mn) / interval_number92intervals = []93x = mn94while x + step <= mx:95intervals.append([x, x := x + step])96if ceil(intervals[-1][1]) != ceil(mx):97intervals.append([x, x := x + step])98return intervals99
100def get_intervals_frequencies(self, data: list[float], interval_number: int) -> list[int]:101var = self.solveB1(data)102var_freq = self.get_frequencies(data)103intervals = self.get_intervals(data, interval_number)104freq = [0] * interval_number105for i in range(interval_number):106for j in range(len(var)):107if intervals[i][0] <= var[j] < intervals[i][1]:108freq[i] += var_freq[j]109for i in range(len(var)):110if var[i] == intervals[-1][1]:111freq[-1] += var_freq[i]112# TODO: сделать проверку крайне правого значения113return freq114
115def get_intervals_relative_frequencies(self, data: list[float], interval_number: int) -> list[float]:116var = self.solveB1(data)117var_rel_freq = self.get_relative_frequencies(data)118intervals = self.get_intervals(data, interval_number)119rel_freq = [0] * interval_number120for i in range(interval_number):121for j in range(len(var)):122if intervals[i][0] <= var[j] < intervals[i][1]:123rel_freq[i] += var_rel_freq[j]124for i in range(len(var)):125if var[i] == intervals[-1][1]:126rel_freq[-1] += var_rel_freq[i]127return rel_freq128
129# -------------решения задания 1-------------------------130def solveB1(self, data: list[float]) -> list[float]:131"""132Решить задачу B1:
133составить вариационный ряд
134:param data: статистические данные
135:return: вариацонный ряд
136"""
137return list(sorted(set(data)))138
139def solveC1(self, data: list[float]) -> tuple[PrettyTable, PrettyTable]:140"""141Решить задачу С1:
142составить статистический ряд частот и ряд отностительных частот;
143построить график для каждого ряда
144:param data: статистические данные
145:return: статистические ряды, (неявно возвращается график plt.show())
146"""
147# получение частот и вар. ряда148freq = self.get_frequencies(data)149relative_freq = self.get_relative_frequencies(data)150
151var = self.solveB1(data)152# Построение графиков153fig1, pol1 = plt.subplots()154fig1, pol2 = plt.subplots()155
156pol1.plot(var, freq)157pol1.set_title("Полигон частот")158
159pol2.plot(var, relative_freq)160pol2.set_title("Полигон относительных частот")161
162# Построение таблиц163freq_table = PrettyTable()164freq_table.add_column("Xi", var)165freq_table.add_column("Ni", freq)166
167relative_freq_table = PrettyTable()168relative_freq_table.add_column("Xi", var)169relative_freq_table.add_column("Wi", [f'{i:.3f}' for i in relative_freq])170
171return freq_table, relative_freq_table172
173def solveD1(self, data: list[float]) -> tuple[str, list[str]]:174"""175Решить задачу D1:
176Дать определение функции распределения;
177Найти функцию распрееделения;
178Построить график для функции.
179:param data: статистические данные
180:return: определение фукнции, функцию распределения, (неявно возвращается график plt.show())
181"""
182
183func_definition = (184"Эмпирической функцией распредления называют функцию F*(x), определяющую для каждого значения x "185"относительну частоту события X < x: F*(x) = n_x/n"186)187
188# получение ф-ции распр.189X = self.solveB1(data)190P = self.get_relative_frequencies(data)191p = 0192Fx = [0] + [p := p + i for i in P]193
194# получение интервалов, для значения ф-ции распр.195intervals = [(X[0] - 1, X[0])]196for i in range(0, len(X) - 1):197intervals.append((X[i], X[i + 1]))198intervals += [(X[-1], X[-1] + 1)]199
200# построение графика201plt.xlim(intervals[0][0], intervals[-1][1])202plt.ylim(0, 1.1)203plt.title("Империческая функция распределения")204# добавление стрелок (xy)<------------(xytext)205for i in range(len(Fx)):206plt.annotate(207'', xy=(intervals[i][0], Fx[i]), xytext=(intervals[i][1], Fx[i]),208arrowprops=dict(width=0.01, headwidth=5)209)210# добавление пунктира211for i in range(len(Fx) - 1):212plt.plot(213[intervals[i][1], intervals[i][1]], [Fx[i], Fx[i + 1]], linestyle="--", color="black"214)215
216# получаем строковое представленние функции217str_intervals = ([f'x <= {X[0]}']218+ [f'{i[0]} < x <= {i[1]}' for i in intervals[1:-1]]219+ [f'x > {X[-1]}'])220str_Fx = [f'если {xs} то F*(x) = {p}' for p, xs in zip([f'{p:0.3f}' for p in Fx], str_intervals)]221
222return func_definition, str_Fx223
224def solveE1(self, data: list[float]) -> tuple[str, float, str, float, str, float, str, float]:225"""226Решить задачу E1:
227Дать определение числовым характеристикам,
228получить эти числовые характеристики
229:param data: статистические данные
230:return: определение числовых характеристик,
231числовые характеристики
232"""
233X = self.solveB1(data)234N = self.get_frequencies(data)235return (236self._sample_mean,237self.sample_mean(X, N),238self._dispersion,239self.dispersion(X, N),240self._standard_deviation,241self.standard_deviation(X, N),242self._unbiased_assessment,243self.unbiased_assessment(X, N)244)245
246# -------------решения задания 2-------------------------247def solveB2(self, data: list[float], interval_number: int) -> PrettyTable:248"""249Решить задачу В2
250получить интервальный ряда чатот и интервальный ряд
251относительных частот.
252Построить гистрограммы для полученных частот
253:param data: статистические данные
254:param interval_number: количество интервалов
255:return: интервальный ряд чатот и интервальный ряд
256относительных частот
257"""
258assert interval_number > 0, "Невозмножно построить интервалы"259
260var = self.solveB1(data)261
262# Получение интервалов263intervals = self.get_intervals(data, interval_number)264
265# Получение интервального ряда частот и относ. частот266freq = self.get_intervals_frequencies(data, interval_number)267rel_freq = self.get_intervals_relative_frequencies(data, interval_number)268
269# Построение таблицы270table = PrettyTable()271table.add_column("Номер интервала - i", [i for i in range(1, interval_number + 1)])272table.add_column("Частичный интервал", [f'{i[0]:0.3f}-{i[1]:0.3f}' for i in intervals])273table.add_column("Сумма частот интервала", freq)274table.add_column("Сумма относительных частот интервала", [f'{i:0.3f}' for i in rel_freq])275
276# Построение гистрограммы277plt.hist(data, bins=interval_number, color='skyblue', edgecolor='black')278plt.title("Гистограмма")279return table280
281def solveC2(self, data: list[float], interval_number: int) -> PrettyTable:282"""283Построить группированный ряд распределения частот
284и группированный ряд распрееделение относительных частот.
285Построить соответствующие полигоны.
286:param data: статистические данные
287:param interval_number: оличество интервалов
288:return: Групированный ряд распределения частот
289и относительных частот
290"""
291middle = [(i[0] + i[1]) / 2 for i in self.get_intervals(data, interval_number)]292# Получение группированного ряда распределения293freq = self.get_intervals_frequencies(data, interval_number)294relative_freq = self.get_intervals_relative_frequencies(data, interval_number)295
296table = PrettyTable()297table.add_column("Середина интервала", [f'{i:0.3f}' for i in middle])298table.add_column("Частоты", freq)299table.add_column("Относительных частоты", [f'{i:0.3f}' for i in relative_freq])300
301# Построение полигонов302fig1, pol1 = plt.subplots()303fig1, pol2 = plt.subplots()304
305pol1.plot(middle, freq)306pol1.set_title("Полигон частот")307
308pol2.plot(middle, relative_freq)309pol2.set_title("Полигон относительных частот")310
311return table312
313def solveD2(self, data: list[float], interval_number: int) -> tuple[list[str], list[str]]:314"""315Решить задачу D2:
316Дать определение функции распределения;
317Найти функции распределений
318для интервального и группированного рядов;
319Построить график для функциий.
320:param data: статистические данные
321:param interval_number: количество интервалов
322:return: функции распределения
323"""
324
325P = self.get_intervals_relative_frequencies(data, interval_number)326intervals = self.get_intervals(data, interval_number)327p = 0328Fx = [0] + [p := p + i for i in P]329
330# получение груп. ряда331mid = [(i[0] + i[1]) / 2 for i in intervals]332
333# построение графиков334fig1, Fx_interv_graph = plt.subplots()335fig2, Fx_mid_graph = plt.subplots()336
337# построение графика ф-ции для инт. ряда338X_axis = [intervals[0][0]] + [i[1] for i in intervals]339Fx_interv_graph.plot(X_axis, Fx)340Fx_interv_graph.set_title("Функция распределения для интервального ряда")341
342# TODO: сделать график как для инт. ряда343#построение графика ф-ции для группированного ряда344mid_by_inter = [(mid[0] - 1, mid[0])]345for i in range(0, len(mid) - 1):346mid_by_inter.append((mid[i], mid[i + 1]))347mid_by_inter += [(mid[-1], mid[-1] + 1)]348Fx_mid_graph.set_xlim(mid_by_inter[0][0], mid_by_inter[-1][1])349Fx_mid_graph.set_ylim(0, 1.1)350Fx_mid_graph.set_title("Функция распределения для групированного ряда")351# добавление стрелок (xy)<------------(xytext)352for i in range(len(Fx)):353Fx_mid_graph.annotate(354'', xy=(mid_by_inter[i][0], Fx[i]), xytext=(mid_by_inter[i][1], Fx[i]),355arrowprops=dict(width=0.01, headwidth=5)356)357# добавление пунктира358for i in range(len(Fx) - 1):359Fx_mid_graph.plot(ё360[mid_by_inter[i][1], mid_by_inter[i][1]], [Fx[i], Fx[i + 1]], linestyle="--", color="black"361)362
363#TODO: починить строковое представление функция364# получаем строковое представленние функции для инт. ряда365str_interv = [f'x < ']366str_interv += [f'x ∈ [{i[0]}, {i[1]})' for i in intervals[0:-1]]367str_interv.append(f'x ∈ ({intervals[-1][0]}, {intervals[-1][1]}]')368Fx = list(map(lambda s: f'{s:0.3f}', Fx))369str_Fx_interv = [f'если {i} то F*(x) = {p}' for p, i in zip(Fx, str_interv)]370
371# получаем строковое представленние функции для груп. ряда372str_mid_intervals = ([f'x <= {mid_by_inter[0][0]}']373+ [f'{i[0]} < x <= {i[1]}' for i in mid_by_inter[1:-1]]374+ [f'x > {mid_by_inter[-1][1]}'])375str_Fx_mid = [f'если {xs} то F*(x) = {p}' for p, xs in zip(Fx, str_mid_intervals)]376
377return str_Fx_interv, str_Fx_mid378
379def solveE2(self):380pass381
382
383if __name__ == "__main__":384data = [1, 1, 5, 3, 7, 1, 3]385interval_number = 5386calc = Calculator()387ans = calc.solveD2(data, interval_number)388for j in ans:389print("------------------------")390for i in j:391print(i)392
393plt.show()394