Python Pygal图表从数据库中提取不匹配值的数据到标签 [英] Python Pygal chart pulling data from database not matching values to labels

查看:96
本文介绍了Python Pygal图表从数据库中提取不匹配值的数据到标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做我的第一个项目,我正在使用Pygal可视化数据库中的某些数据。



我正在使用最新版本的Python(3.6.5) ),Flask,Pygal和我的IDE是Pycharm



该项目是一个简单的预算应用程序,其中输入了每月支出的计划预算,然后输入了实际金额费用/项目(例如每月的汽车费用,例如汽油)。



我使用Pygal显示2个条形图。第一个(按预期工作)显示计划的总金额与总的实际金额:





第二个图表显示了每笔费用/项目的计划vs实际费用(例如,每月的汽车支出,如汽油)



问题一面临的是图表混合了标签和金额。它们会根据输入顺序而不是项目类型显示在图表中。



例如:





在上图中,有3个项目:Masina(汽车),Salariu(工资)和Economii(储蓄)。



由蓝色列表示的金额(实际金额)应显示在标签Economii上,而不是Masina下,并且我不要紧在数据库中将其作为第一个实际值输入。



此外,在数据库中为相同费用项目(在我们的情况下为Economii)添加更多实际金额,只会添加更多列并且不会在同一列中进行汇总:





这是我正在使用的数据库查询功能:

  def GraphData():
BASE_DIR = os.path.dirname(os.path.abspath(__ file__))
db_path = os.path.join(BASE_DIR,'budget_db.db')
与sqlite3.connect(db_path) as db:
c = db.cursor()
d = db.cursor()
c.execute('SELECT标题,类别,名称,PLANET_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()
返回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 data_planned中的planned_row:
title_planned.append(planned_row [2])
value_planned.append(planned_row [3])
forual_row在data_actual中:
title_actual.append(actual_row [2])
value_actual.append(actual_row [3])

图= pygal.Bar(title = u'总计划值VS总实际值')
graph.add('Planned',[{'value':sum(value_planned),'label':'计划预算总额:'}])
graph.add ('Actual',[{'value':sum(value_actual),'label':'实际金额总计:'}])
graph_data = graph.render_data_uri()

graph_all = pygal.Bar(title = u'每件商品的计划预算与每件商品的实际金额')
graph_all.x_label s = title_planned
graph_all.add('Planned',value_planned)
graph_all.add('Actual',value_actual)
graph_all_data = graph_all.render_data_uri()

返回render_template('home.html',graph_data = graph_data,graph_all_data = graph_all_data)

编辑:



我一直在尝试使用路线中的2个字典,将支出项作为字典键( title_planned_sum / title_actual_sum )和金额作为dict值( value_planned_sum / value_actual_sum ):

  tv_planned = dict(zip(title(plan_title,value_planned))
tv_planned_sum = {title_planned_sum:title_planned_sum的总和(value_planned_sum),tv_planned.items()中的value_planned_sum}

tv_actual = dict(zip(title_actual,value_actual))
tv_actual_sum = {title_actual_sum:总和(值)对于title_actual_sum,在tv_actual.items()}中的value_actual_sum,

这是完整的路线:

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

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

for data_planned中的planned_row:
title_planned.append(planned_row [2])
value_planned.append(planned_row [3])
data_actual中的actual_row的

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:title_planned_sum的sum(value_planned_sum),tv_planned.items()中的value_planned_sum}

tv_actual = dict(zip(title(act_actual,value_actual)))
tv_actual_sum = {title_actual_sum:title_actual_sum的sum(value_actual_sum),tv_actual.items()中的value_actual_sum}

图= pygal.Bar(title = u'To总计划值与总实际值')
graph.add('Planned',[{'value':sum(value_planned),'label':'计划预算总额:'}])
graph.add('Actual',[{'value':sum(value_actual),'label':'实际总金额:'}])
graph_data = graph.render_data_uri()

graph_all = pygal.Bar(title = u'每个项目的计划预算与每个项目的实际金额')
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)

但是,当然,现在我收到此调试错误:



< blockquote>

TypeError: float对象不可迭代


这是因为,在我要使用的2个词典中,我试图对价值进行求和对于每个收到多个具有 sum(value_planned_sum) 的值的键。

解决方案

我成功了!



<最终,我意识到自己的问题过于复杂了,于是我掏出笔和纸,开始做一些伪代码,看看代码的第一步在哪里,我可以轻松地计算出使我头疼。



第1步:在我的路线中,我可以创建一个包含嵌套元组的列表(每个元素包含2个元素:str和float)



第2步:现在,如果某些元组在索引[0]上具有相同的元素,如何求和在索引[1]上的float元素?



因此,我在reddit.com/r/上问了这个问题learningpython 和用户 diech 给了我一个我可以成功使用的想法:导入 itertools 包并从中使用 groupby()



这是我的路线代码现在的样子:

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

title_planned = []
value_planned = []
title_actual = []
value_actual = []
计划的= []
实际= []

为data_planned中的planned_row:
title_planned.append(planned_row [2])
value_planned.append(planned_row [3])
planned_list = zip(title_planned,value_planned)
对于密钥,组在itertools.groupby(sorted(planned_list),lambda x:x [0])中:
asum = 0
对于组中的i:
asum + = i [1]
planning.append((key,asum))

planned_dict = dict(计划)

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

actual_dict = dict(act)

图= pygal.Bar(title = u'总计划值与Tota l实际值')
graph.add('Planned',[{'value':sum(value_planned),'label':'计划预算总额:'}])
graph.add( 'Actual',[{'value':sum(value_actual),'label':'实际金额总计:'}])
graph_data = graph.render_data_uri()

graph_all = pygal.Bar(title = u'每件商品的计划预算与每件商品的实际金额')
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)


I am working on my first project and I am using Pygal to visualize some data from a database.

I am using the latest version of Python (3.6.5), Flask, Pygal and my IDE is Pycharm

The project is a simple budget application in which one enters the planned budget for a monthly expenditure and then the actual amounts for that expense/item (e.g. monthly car expenses, like gas).

I use Pygal to show 2 bar charts. The first one (which works as intended) shows a total planned amounts vs total actual amounts:

The second chart shows the planned vs actual per expense/item (e.g. monthly car expenses, like gas)

The issue I am facing is that the chart mixes up the labels and amounts. They show up in the chart based on the order they are entered, not on the item type.

For example:

In the above image, the are 3 items: Masina (car), Salariu (salary) and Economii (savings).

The amount represented by the blue column (the actual amount) should show up under the label Economii, not under Masina and it should not matter that I have entered it as the first actual in the database.

Also, adding more actual amounts for the same expenses item (Economii in our case) in the database simply adds more columns and it does not sum it up on the same column:

This is the database query function I am using:

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

Below is the route I have created for both of the charts. The labels are pulled from the title_planned list and I have a feeling that the issue I am facing is because I am creating lists and I am appending them. I think I should create dictionaries, but I have not idea how without messing everything else up:

 @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)

Edit:

I have been trying to do it using 2 dictionaries in the route with the expense item as dict key (title_planned_sum / title_actual_sum) and the amount as dict value (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()}

Here is the full 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)

But of course, now I am getting this debug error:

TypeError: 'float' object is not iterable

And this is because, in the 2 dictionaries I am trying to work with, I am trying to sum the values for each key that receives multiple values with sum(value_planned_sum).

解决方案

I got it working!

In the end I realized I was over-complicating my question, so I pulled out a pen and paper and started doing some pseudo-code to see where was the first step in my code where I could comfortably calculate the floats sum that was causing me head-aches.

Step 1: In my route, I could create a list containing nested tuples (with 2 elements each: str and float)

Step 2: Now, if some of the tuples had the same elements on index [0], how do I sum the float elements on index [1]?

So, I asked the this question on reddit.com/r/learnpython and the user diesch gave me an idea that I could use successfully: to import the itertools package and from it, to use groupby().

Here is how my route code looks now:

@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)    

这篇关于Python Pygal图表从数据库中提取不匹配值的数据到标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆