Python Диаграмма Pygal, извлекающая данные из базы данных, не соответствующие значениям меток - PullRequest
0 голосов
/ 07 июня 2018

Я работаю над своим первым проектом и использую Pygal для визуализации некоторых данных из базы данных.

Я использую последнюю версию Python (3.6.5), Flask, Pygal и моя IDEPycharm

Проект представляет собой простое бюджетное приложение, в котором вводится плановый бюджет для ежемесячных расходов, а затем фактические суммы для этих расходов / статей (например, ежемесячные расходы на автомобиль, такие как газ).

Я использую Pygal, чтобы показать 2 гистограммы.Первый (который работает как задумано) показывает общие плановые суммы против общих фактических сумм:

enter image description here

Второй график показывает запланированные против фактических расходов/ item (например, ежемесячные расходы на автомобиль, например, бензин)

Проблема, с которой я сталкиваюсь, заключается в том, что диаграмма смешивает метки и суммы.Они отображаются на графике в соответствии с порядком их ввода, а не с типом позиции.

Например:

enter image description here

На изображении выше представлены 3 элемента: Masina (автомобиль), Salariu (зарплата) и Economii (сбережения).

Сумма, обозначенная синей колонкой (фактическая сумма), должна отображаться под меткой Economii., не под Масиной, и не должно иметь значения, что я ввел его в качестве первого фактического в базе данных.

Кроме того, добавление большего количества фактических сумм для той же статьи расходов (в нашем случае Economii) в базе данных просто добавляетбольше столбцов, и он не суммирует его в одном столбце:

enter image description here

Это функция запроса к базе данных, которую я использую:

def GraphData():
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
db_path = os.path.join(BASE_DIR, 'budget_db.db')
with sqlite3.connect(db_path) as db:
    c = db.cursor()
    d = db.cursor()
    c.execute('SELECT title, category, name, planned_amount_month FROM Post')
    d.execute('SELECT title_actual, category_actual, actual_amount_name, actual_amount FROM ActualPost')
    data_planned = c.fetchall()
    data_actual = d.fetchall()
return data_planned, data_actual

Ниже приведен маршрут, который я создал для обеих карт.Метки извлекаются из списка title_planned, и я чувствую, что проблема, с которой я сталкиваюсь, заключается в том, что я создаю списки и добавляю их.Я думаю, что я должен создать словари, но я понятия не имею, как, не испуская все остальное:

 @posts.route("/home")
def graphing():
data_planned, data_actual = GraphData()
title_planned = []
value_planned = []
title_actual = []
value_actual = []
for planned_row in data_planned:
    title_planned.append(planned_row[2])
    value_planned.append(planned_row[3])
for actual_row in data_actual:
    title_actual.append(actual_row[2])
    value_actual.append(actual_row[3])

graph = pygal.Bar(title=u'Total Planned Values vs Total Actual Values')
graph.add('Planned', [{'value': sum(value_planned), 'label': 'Total for Planned Budget:'}])
graph.add('Actual', [{'value': sum(value_actual), 'label': 'Total for Actual Amounts:'}])
graph_data = graph.render_data_uri()

graph_all = pygal.Bar(title=u'Planned Budget per item vs Actual Amounts per item')
graph_all.x_labels = title_planned
graph_all.add('Planned', value_planned)
graph_all.add('Actual', value_actual)
graph_all_data = graph_all.render_data_uri()

return render_template('home.html', graph_data=graph_data, graph_all_data=graph_all_data)

Редактировать:

Я пытался сделать это с помощью2 словаря в маршруте с пунктом расходов в качестве ключа dict (title_planned_sum / title_actual_sum) и суммой в качестве значения dict (value_planned_sum / value_actual_sum):

tv_planned = dict(zip(title_planned, value_planned))
tv_planned_sum = {title_planned_sum: sum(value_planned_sum) for title_planned_sum, value_planned_sum in tv_planned.items()}

tv_actual = dict(zip(title_actual, value_actual))
tv_actual_sum = {title_actual_sum: sum(value_actual_sum) for title_actual_sum, value_actual_sum in tv_actual.items()}

Вот полныйroute:

@posts.route("/home")
def graphing():
    data_planned, data_actual = GraphData()

    title_planned = []
    value_planned = []
    title_actual = []
    value_actual = []

    for planned_row in data_planned:
        title_planned.append(planned_row[2])
        value_planned.append(planned_row[3])

    for actual_row in data_actual:
        title_actual.append(actual_row[2])
        value_actual.append(actual_row[3])

    tv_planned = dict(zip(title_planned, value_planned))
    tv_planned_sum = {title_planned_sum: sum(value_planned_sum) for title_planned_sum, value_planned_sum in tv_planned.items()}

    tv_actual = dict(zip(title_actual, value_actual))
    tv_actual_sum = {title_actual_sum: sum(value_actual_sum) for title_actual_sum, value_actual_sum in tv_actual.items()}

    graph = pygal.Bar(title=u'Total Planned Values vs Total Actual Values')
    graph.add('Planned', [{'value': sum(value_planned), 'label': 'Total for Planned Budget:'}])
    graph.add('Actual', [{'value': sum(value_actual), 'label': 'Total for Actual Amounts:'}])
    graph_data = graph.render_data_uri()

    graph_all = pygal.Bar(title=u'Planned Budget per item vs Actual Amounts per item')
    graph_all.x_labels = title_planned
    graph_all.add('Planned', tv_planned_sum)
    graph_all.add('Actual', tv_actual_sum)
    graph_all_data = graph_all.render_data_uri()

    return render_template('home.html', graph_data=graph_data, graph_all_data=graph_all_data)

Но, конечно, теперь я получаю эту ошибку отладки:

TypeError: 'float' object is not iterable

И это потому, что вВ двух словарях, с которыми я пытаюсь работать, я пытаюсь суммировать значения для каждого ключа, который получает несколько значений, с sum(value_planned_sum).

1 Ответ

0 голосов
/ 10 июня 2018

Я все заработал!

В конце я понял, что слишком усложняю свой вопрос, поэтому я вытащил ручку и бумагу и начал делать какой-то псевдокод, чтобы увидетьгде был первый шаг в моем коде, где я мог удобно рассчитать сумму с плавающей точкой, которая вызывала у меня головную боль.

Шаг 1: На моем маршруте я мог бы создать список, содержащий вложенные кортежи (с 2 элементами каждый: str и float)

Шаг 2: Теперь, если некоторые из кортежей имели одинаковыеэлементы по индексу [0], как мне суммировать элементы с плавающей точкой по индексу [1]?

Итак, я задал этот вопрос на reddit.com/r/learnpython и пользователю diesch дал мне идею, которую я мог бы успешно использовать: чтобы импортировать пакет itertools и из него использовать groupby().

Вот как теперь выглядит мой код маршрута:

@posts.route("/home")
def graphing():
    data_planned, data_actual = GraphData()

    title_planned = []
    value_planned = []
    title_actual = []
    value_actual = []
    planned = []
    actual = []

    for planned_row in data_planned:
        title_planned.append(planned_row[2])
        value_planned.append(planned_row[3])
        planned_list = zip(title_planned, value_planned)
        for key, group in itertools.groupby(sorted(planned_list), lambda  x: x[0]):
            asum = 0
            for i in group:
                asum += i[1]
            planned.append((key, asum))

    planned_dict = dict(planned)

    for actual_row in data_actual:
        title_actual.append(actual_row[2])
        value_actual.append(actual_row[3])
        actual_list = zip(title_actual, value_actual)
        for key, group in itertools.groupby(sorted(actual_list), lambda  x: x[0]):
            asum = 0
            for i in group:
                asum += i[1]
            actual.append((key, asum))

    actual_dict = dict(actual)

    graph = pygal.Bar(title=u'Total Planned Values vs Total Actual Values')
    graph.add('Planned', [{'value': sum(value_planned), 'label': 'Total for Planned Budget:'}])
    graph.add('Actual', [{'value': sum(value_actual), 'label': 'Total for Actual Amounts:'}])
    graph_data = graph.render_data_uri()

    graph_all = pygal.Bar(title=u'Planned Budget per item vs Actual Amounts per item')
    graph_all.x_labels = title_planned
    graph_all.add('Planned', planned_dict)
    graph_all.add('Actual', actual_dict)
    graph_all_data = graph_all.render_data_uri()

    return render_template('home.html', graph_data=graph_data, graph_all_data=graph_all_data)    
...