Только донастроить вывод и допилить оценку.
This commit is contained in:
parent
4356e23d3b
commit
a73b247471
@ -2,7 +2,7 @@ import pandas as pd
|
||||
|
||||
def covertorDataFrame():
|
||||
|
||||
df = pd.read_csv("../../res/Stores.csv")
|
||||
df = pd.read_csv("res/Stores.csv")
|
||||
|
||||
# кол-во строчек для считывания
|
||||
countMainRows = 35
|
||||
@ -27,15 +27,13 @@ def covertorDataFrame():
|
||||
'Store_Sales': str
|
||||
}
|
||||
|
||||
mainDF = mainDF.astype(convert_dict)
|
||||
newMainDF = mainDF.astype(convert_dict)
|
||||
|
||||
# генеральная выборка
|
||||
newDfGeneral = mainDF.iloc[0:25]
|
||||
newDfGeneral = newMainDF.iloc[0:25]
|
||||
|
||||
# выборка для проверки
|
||||
newDfSupport = mainDF.iloc[25:35]
|
||||
|
||||
print(newDfSupport[['TextStoreSales', 'TextStoreSales', 'TextStoreArea']])
|
||||
newDfSupport = newMainDF.iloc[25:35]
|
||||
|
||||
return [newDfGeneral[['TextDailyCustomerCount', 'TextStoreArea', 'TextStoreSales']],
|
||||
newDfSupport[['TextDailyCustomerCount', 'TextStoreArea', 'TextStoreSales']]]
|
||||
|
117
LabWork01/LabWork6/ReservCopy/CopyTree.py
Normal file
117
LabWork01/LabWork6/ReservCopy/CopyTree.py
Normal file
@ -0,0 +1,117 @@
|
||||
import math
|
||||
import pandas as pd
|
||||
from functools import reduce
|
||||
|
||||
from LabWork01.LabWork6.ConvertorDataFrame import covertorDataFrame
|
||||
|
||||
# Дата сет
|
||||
# data = [
|
||||
# ["красный", "квадрат", "красный квадрат"],
|
||||
# ["красный", "прямоугольник", "красный прямоугольник"],
|
||||
# ["красный", "круг", "красный круг"],
|
||||
# ["красный", "треугольник", "красный треугольник"],
|
||||
#
|
||||
# ["зеленый", "квадрат", "зеленый квадрат"],
|
||||
# ["зеленый", "треугольник", "зеленый треугольник"],
|
||||
# ["зеленый", "круг", "зеленый круг"],
|
||||
# ]
|
||||
# df0 = pd.DataFrame(data)
|
||||
# df0.columns = ["цвет", "форма", "результат"]
|
||||
|
||||
df0 = covertorDataFrame()[0]
|
||||
|
||||
# Лямбда-выражение для распределения значений, аргумент - pandas.Series,
|
||||
# возвращаемое значение - массив с количеством каждого из значений
|
||||
# Из вводных данных s с помощью value_counts() находим частоту каждого из значений,
|
||||
# и пока в нашем словаре есть элементы, будет работать цикл, запускаемый items().
|
||||
# Чтобы выходные данные не менялись с каждым запуском цикла, мы используем sorted,
|
||||
# который меняет порядок от большего к меньшему
|
||||
# В итоге, генерируется массив, содержащий строку из следующих компонентов: ключ (k) и значение (v).
|
||||
cstr = lambda s: [k + ":" + str(v) for k, v in sorted(s.value_counts().items())]
|
||||
|
||||
# Структура данных Decision Tree
|
||||
tree = {
|
||||
# name: Название этого нода (узла)
|
||||
"name": "decision tree " + df0.columns[-1] + " " + str(cstr(df0.iloc[:, -1])),
|
||||
# df: Данные, связанные с этим нодом (узлом)
|
||||
"df": df0,
|
||||
# edges: Список ребер (ветвей), выходящих из этого узла,
|
||||
# или пустой массив, если ниже нет листового узла.
|
||||
"edges": [],
|
||||
}
|
||||
|
||||
# Генерацию дерева, у узлов которого могут быть ветви, сохраняем в open
|
||||
open = [tree]
|
||||
|
||||
# Лямба-выражение для вычесления энтропии.
|
||||
# Аргумент - pandas.Series、возвращаемое значение - число энтропии
|
||||
entropy = lambda s: -reduce(lambda x, y: x + y, map(lambda x: (x / len(s)) * math.log2(x / len(s)), s.value_counts()))
|
||||
|
||||
# Зацикливаем, пока open не станет пустым
|
||||
while (len(open) != 0):
|
||||
# Вытаскиваем из массива open первый элемент,
|
||||
# и вытаскиваем данные, хранящиеся в этом узле
|
||||
n = open.pop(0)
|
||||
df_n = n["df"]
|
||||
|
||||
# В случае, если энтропия этого узла равна 0, мы больше не можем вырастить из него новые ветви
|
||||
# поэтому прекращаем ветвление от этого узла
|
||||
if 0 == entropy(df_n.iloc[:, -1]):
|
||||
continue
|
||||
# Создаем переменную, в которую будем сохранять список значений атрибута с возможностью разветвления
|
||||
attrs = {}
|
||||
# Исследуем все атрибуты, кроме последнего столбца класса атрибутов
|
||||
for attr in df_n.columns[:-1]:
|
||||
# Создаем переменную, которая хранит значение энтропии при ветвлении с этим атрибутом,
|
||||
# данные после разветвления и значение атрибута, который разветвляется.
|
||||
attrs[attr] = {"entropy": 0, "dfs": [], "values": []}
|
||||
# Исследуем все возможные значения этого атрибута.
|
||||
# Кроме того, sorted предназначен для предотвращения изменения порядка массива,
|
||||
# из которого были удалены повторяющиеся значения атрибутов, при каждом его выполнении.
|
||||
for value in sorted(set(df_n[attr])):
|
||||
# Фильтруем данные по значению атрибута
|
||||
df_m = df_n.query(attr + "=='" + value + "'")
|
||||
# Высчитываем энтропию, данные и значения сохрнаяем
|
||||
attrs[attr]["entropy"] += entropy(df_m.iloc[:, -1]) * df_m.shape[0] / df_n.shape[0]
|
||||
attrs[attr]["dfs"] += [df_m]
|
||||
attrs[attr]["values"] += [value]
|
||||
pass
|
||||
pass
|
||||
# Если не осталось ни одного атрибута, значение которого можно разделить,
|
||||
# прерываем исследование этого узла.
|
||||
if len(attrs) == 0:
|
||||
continue
|
||||
# Получаем атрибут с наименьшим значением энтропии
|
||||
attr = min(attrs, key=lambda x: attrs[x]["entropy"])
|
||||
# Добавляем каждое значение разветвленного атрибута
|
||||
# и данные, полученные после разветвления, в наше дерево и в open.
|
||||
for d, v in zip(attrs[attr]["dfs"], attrs[attr]["values"]):
|
||||
m = {"name": attr + "=" + v, "edges": [], "df": d.drop(columns=attr)}
|
||||
n["edges"].append(m)
|
||||
open.append(m)
|
||||
pass
|
||||
|
||||
# Выводим дата сет
|
||||
print(df0, "\n-------------")
|
||||
|
||||
|
||||
# Метод преобразования дерева в символы, аргуметы - tree:структура данных древа,
|
||||
# indent:присоединяймый к дочернему узлу indent,
|
||||
# Возвращаемое значение - символьное представление древа.
|
||||
# Этот метод вызывается рекурсивно для преобразования всех данных в дереве в символы.
|
||||
def tstr(tree, indent=""):
|
||||
# Создаем символьное представление этого узла.
|
||||
# Если этот узел является листовым узлом (количество элементов в массиве ребер равно 0),
|
||||
# частотное распределение последнего столбца данных df, связанных с деревом, преобразуется в символы.
|
||||
s = indent + tree["name"] + str(cstr(tree["df"].iloc[:, -1]) if len(tree["edges"]) == 0 else "") + "\n"
|
||||
# Зацикливаем все ветви этого узла.
|
||||
for e in tree["edges"]:
|
||||
# Добавляем символьное представление дочернего узла к символьному представлению родительского узла.
|
||||
# Добавляем еще больше символов к indent этого узла.
|
||||
s += tstr(e, indent + " ")
|
||||
pass
|
||||
return s
|
||||
|
||||
|
||||
# Выводим древо в его символьном представлении.
|
||||
print(tstr(tree))
|
@ -1,32 +1,11 @@
|
||||
import math
|
||||
import pandas as pd
|
||||
from functools import reduce
|
||||
|
||||
from LabWork01.LabWork6.ConvertorDataFrame import covertorDataFrame
|
||||
|
||||
# Дата сет
|
||||
# data = [
|
||||
# ["красный", "квадрат", "красный квадрат"],
|
||||
# ["красный", "прямоугольник", "красный прямоугольник"],
|
||||
# ["красный", "круг", "красный круг"],
|
||||
# ["красный", "треугольник", "красный треугольник"],
|
||||
#
|
||||
# ["зеленый", "квадрат", "зеленый квадрат"],
|
||||
# ["зеленый", "треугольник", "зеленый треугольник"],
|
||||
# ["зеленый", "круг", "зеленый круг"],
|
||||
# ]
|
||||
# df0 = pd.DataFrame(data)
|
||||
# df0.columns = ["цвет", "форма", "результат"]
|
||||
|
||||
# дата-сет
|
||||
df0 = covertorDataFrame()[0]
|
||||
|
||||
# Лямбда-выражение для распределения значений, аргумент - pandas.Series,
|
||||
# возвращаемое значение - массив с количеством каждого из значений
|
||||
# Из вводных данных s с помощью value_counts() находим частоту каждого из значений,
|
||||
# и пока в нашем словаре есть элементы, будет работать цикл, запускаемый items().
|
||||
# Чтобы выходные данные не менялись с каждым запуском цикла, мы используем sorted,
|
||||
# который меняет порядок от большего к меньшему
|
||||
# В итоге, генерируется массив, содержащий строку из следующих компонентов: ключ (k) и значение (v).
|
||||
cstr = lambda s: [k + ":" + str(v) for k, v in sorted(s.value_counts().items())]
|
||||
|
||||
# Структура данных Decision Tree
|
||||
@ -35,8 +14,7 @@ tree = {
|
||||
"name": "decision tree " + df0.columns[-1] + " " + str(cstr(df0.iloc[:, -1])),
|
||||
# df: Данные, связанные с этим нодом (узлом)
|
||||
"df": df0,
|
||||
# edges: Список ребер (ветвей), выходящих из этого узла,
|
||||
# или пустой массив, если ниже нет листового узла.
|
||||
# edges: Список ребер (ветвей), выходящих из этого узла, или пустой массив, если ниже нет листового узла.
|
||||
"edges": [],
|
||||
}
|
||||
|
||||
@ -49,42 +27,33 @@ entropy = lambda s: -reduce(lambda x, y: x + y, map(lambda x: (x / len(s)) * mat
|
||||
|
||||
# Зацикливаем, пока open не станет пустым
|
||||
while (len(open) != 0):
|
||||
# Вытаскиваем из массива open первый элемент,
|
||||
# и вытаскиваем данные, хранящиеся в этом узле
|
||||
|
||||
n = open.pop(0)
|
||||
df_n = n["df"]
|
||||
|
||||
# В случае, если энтропия этого узла равна 0, мы больше не можем вырастить из него новые ветви
|
||||
# поэтому прекращаем ветвление от этого узла
|
||||
if 0 == entropy(df_n.iloc[:, -1]):
|
||||
continue
|
||||
# Создаем переменную, в которую будем сохранять список значений атрибута с возможностью разветвления
|
||||
|
||||
attrs = {}
|
||||
# Исследуем все атрибуты, кроме последнего столбца класса атрибутов
|
||||
|
||||
for attr in df_n.columns[:-1]:
|
||||
# Создаем переменную, которая хранит значение энтропии при ветвлении с этим атрибутом,
|
||||
# данные после разветвления и значение атрибута, который разветвляется.
|
||||
|
||||
attrs[attr] = {"entropy": 0, "dfs": [], "values": []}
|
||||
# Исследуем все возможные значения этого атрибута.
|
||||
# Кроме того, sorted предназначен для предотвращения изменения порядка массива,
|
||||
# из которого были удалены повторяющиеся значения атрибутов, при каждом его выполнении.
|
||||
|
||||
for value in sorted(set(df_n[attr])):
|
||||
# Фильтруем данные по значению атрибута
|
||||
df_m = df_n.query(attr + "=='" + value + "'")
|
||||
# Высчитываем энтропию, данные и значения сохрнаяем
|
||||
|
||||
attrs[attr]["entropy"] += entropy(df_m.iloc[:, -1]) * df_m.shape[0] / df_n.shape[0]
|
||||
attrs[attr]["dfs"] += [df_m]
|
||||
attrs[attr]["values"] += [value]
|
||||
pass
|
||||
pass
|
||||
# Если не осталось ни одного атрибута, значение которого можно разделить,
|
||||
# прерываем исследование этого узла.
|
||||
|
||||
if len(attrs) == 0:
|
||||
continue
|
||||
# Получаем атрибут с наименьшим значением энтропии
|
||||
|
||||
attr = min(attrs, key=lambda x: attrs[x]["entropy"])
|
||||
# Добавляем каждое значение разветвленного атрибута
|
||||
# и данные, полученные после разветвления, в наше дерево и в open.
|
||||
|
||||
for d, v in zip(attrs[attr]["dfs"], attrs[attr]["values"]):
|
||||
m = {"name": attr + "=" + v, "edges": [], "df": d.drop(columns=attr)}
|
||||
n["edges"].append(m)
|
||||
@ -94,24 +63,16 @@ while (len(open) != 0):
|
||||
# Выводим дата сет
|
||||
print(df0, "\n-------------")
|
||||
|
||||
|
||||
# Метод преобразования дерева в символы, аргуметы - tree:структура данных древа,
|
||||
# indent:присоединяймый к дочернему узлу indent,
|
||||
# Возвращаемое значение - символьное представление древа.
|
||||
# Этот метод вызывается рекурсивно для преобразования всех данных в дереве в символы.
|
||||
def tstr(tree, indent=""):
|
||||
# Создаем символьное представление этого узла.
|
||||
# Если этот узел является листовым узлом (количество элементов в массиве ребер равно 0),
|
||||
# частотное распределение последнего столбца данных df, связанных с деревом, преобразуется в символы.
|
||||
s = indent + tree["name"] + str(cstr(tree["df"].iloc[:, -1]) if len(tree["edges"]) == 0 else "") + "\n"
|
||||
# Зацикливаем все ветви этого узла.
|
||||
for e in tree["edges"]:
|
||||
# Добавляем символьное представление дочернего узла к символьному представлению родительского узла.
|
||||
# Добавляем еще больше символов к indent этого узла.
|
||||
s += tstr(e, indent + " ")
|
||||
pass
|
||||
return s
|
||||
|
||||
def getStringTree():
|
||||
return tstr(tree)
|
||||
|
||||
# Выводим древо в его символьном представлении.
|
||||
print(tstr(tree))
|
||||
|
@ -1,6 +1,6 @@
|
||||
import os
|
||||
import secrets
|
||||
from flask import Flask, redirect, url_for, request, render_template, session
|
||||
from flask import Flask, request, render_template, session
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from LabWork01.AnalysCustomers import analysCustomersDataFrame
|
||||
@ -15,6 +15,7 @@ from LabWork01.LabWork3.DeletePng import deleteAllPng
|
||||
from LabWork01.LabWork4.SiteSearch import SiteSearch
|
||||
from LabWork01.LabWork5.create_plot import create_plot_jpg
|
||||
from LabWork01.LabWork6.ConvertorDataFrame import covertorDataFrame
|
||||
from LabWork01.LabWork6.Tree import getStringTree
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@ -45,9 +46,8 @@ search_engine.add("https://www.kaggle.com/datasets/surajjha101/forbes-billionair
|
||||
search_engine.add("https://www.kaggle.com/datasets/fedesoriano/stroke-prediction-dataset", [ "heart_disease" , "bmi", "stroke" ])
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@app.route("/", methods=['GET','POST'])
|
||||
def home():
|
||||
covertorDataFrame(listShops)
|
||||
return render_template('main_page.html', context=[], main_img=[], messages=[], image_names=[], tableAnalys=[], titles=[''], listTypes=listTypes, countNull=countNull, firstRow=1, secondRow=4, firstColumn=1, secondColumn=4)
|
||||
|
||||
@app.route("/showDiapason", methods=['GET','POST'])
|
||||
@ -214,6 +214,12 @@ def get_plot_image():
|
||||
listTypes=listTypes, countNull=countNull, firstRow=1,
|
||||
secondRow=4, firstColumn=1, secondColumn=4)
|
||||
|
||||
@app.route('/createTree', methods=['GET'])
|
||||
def get_data_Tree():
|
||||
DataTree = getStringTree()
|
||||
|
||||
return render_template('tree_page.html', DataTree=DataTree)
|
||||
|
||||
if __name__=="__main__":
|
||||
app.run(debug=True)
|
||||
|
||||
|
@ -31,6 +31,11 @@
|
||||
<button type="submit" class="btn btn-primary mb-3">Запуск фильтра</button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="/createTree" method="get">
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-primary mb-3">Построить дерево</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<table>
|
||||
|
30
LabWork01/templates/tree_page.html
Normal file
30
LabWork01/templates/tree_page.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for( 'static', filename='index.css', v=1)}}">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
<title>Tree</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<form action="/" method="get">
|
||||
<div class="mb-5 mt-3">
|
||||
<label class="form-label">Вывод дерева</label>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input type=submit value='Главная'>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="">
|
||||
<p>{{ DataTree }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user