Matplotlib Piechart Auto Процент не работает - PullRequest
0 голосов
/ 26 июня 2018

Я использую python и matplotlib для создания отчета о стоимости PDF для AWS, который отправляется еженедельно.Я пытаюсь добавить разбивку услуг по стоимости с помощью круговой диаграммы, чтобы показать, сколько каждая услуга составляет общую стоимость.Тем не менее, круговая диаграмма, которую я показываю, на самом деле не выполняет автоматические проценты.На круговой диаграмме все значения находятся в одинаковых 12-часовых позициях и спред для них отсутствует.

Не совсем уверен, что я делаю здесь неправильно.Списки размеров, меток и цветов имеют одинаковый размер.Размеры или список значений являются целыми числами, я пробовал float и strings.Не выдает ошибку, просто неправильно формирует график.

Пустая круговая диаграмма. Pie Chart

Список значений, которые пытается использовать диаграмма: Sizes List

Список цветов, которые пытается использовать диаграмма: Colors List

Список меток, которые пытается использовать диаграмма. List of Labels

Код:

labels = []
sizes = []
colors = []

for cost in cost_dict:
    if cost_dict[cost]["UnblendedCost"] >= 0.1:
        labels.append(cost)
        sizes.append(int(cost_dict[cost]["UnblendedCost"]))

number_of_colors = len(sizes)
colors = []
color_choices = ['gold', 'yellowgreen', 'lightcoral', 'lightskyblue', 'yellowgreen', 'lightcoral', 'lightskyblue', 'purple', 'grey']
count = 0

for color in range(0,number_of_colors):
    colors.append(color_choices[count])
    count += 1

plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True, startangle=90)

plt.axis('equal')

plt.savefig("cost-pie2.png")

Полный скрипт:

import boto3
import datetime
from fpdf import FPDF
import calendar
from dateutil.relativedelta import relativedelta
import collections

import matplotlib

matplotlib.use('Agg')


import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import operator
import sys


#number_of_months = sys.argv[1]
number_of_months = 4


def get_aws_data(first_date, current_date):

    client = boto3.client('ce')

    Dimensions = client.get_dimension_values(
        TimePeriod={
            'Start': first_date,
            'End': current_date
        },
        Dimension='SERVICE',
        Context='COST_AND_USAGE'
    )

    cost_dict = {}

    for dimension in Dimensions["DimensionValues"]:
        dimension_to_search = str(dimension["Value"])
        response = client.get_cost_and_usage(
            TimePeriod={
                'Start': first_date,
                'End': current_date
            },
            Granularity='MONTHLY',
            Filter={"Dimensions": {
                    "Key": "SERVICE",
                    "Values": [
                        dimension_to_search
                    ]
            }},
            Metrics=[
                'BlendedCost',
                'UnblendedCost',
                'UsageQuantity',
            ],
            GroupBy=[
                {
                    "Type": "DIMENSION",
                    "Key": "SERVICE"
                },
            ]
        )

        for result in response["ResultsByTime"]:
            for cost in result["Groups"]:
                if cost["Metrics"]["BlendedCost"]["Amount"] > 0 or cost["Metrics"]["UnblendedCost"]["Amount"] > 0:
                    if cost_dict.has_key(cost["Keys"][0]):
                        cost_dict[cost["Keys"][0]]["BlendedCost"] = float(cost["Metrics"]["BlendedCost"]["Amount"]) + float(cost_dict[cost["Keys"][0]]["BlendedCost"])
                        cost_dict[cost["Keys"][0]]["UnblendedCost"] = float(cost["Metrics"]["UnblendedCost"]["Amount"]) + float(cost_dict[cost["Keys"][0]]["UnblendedCost"])
                        cost_dict[cost["Keys"][0]]["Usage"] = float(cost["Metrics"]["UsageQuantity"]["Amount"]) + float(cost_dict[cost["Keys"][0]]["Usage"])
                    else:
                        cost_dict[cost["Keys"][0]] = {}
                        cost_dict[cost["Keys"][0]]["BlendedCost"] = {}
                        cost_dict[cost["Keys"][0]]["UnblendedCost"] = {}
                        cost_dict[cost["Keys"][0]]["Usage"] = {}
                        cost_dict[cost["Keys"][0]]["BlendedCost"] = float(cost["Metrics"]["BlendedCost"]["Amount"])
                        cost_dict[cost["Keys"][0]]["UnblendedCost"] = float(cost["Metrics"]["UnblendedCost"]["Amount"])
                        cost_dict[cost["Keys"][0]]["Usage"] = float(cost["Metrics"]["UsageQuantity"]["Amount"])
    return cost_dict

def generate_monthly_cost_report(months):

    dates_dict = collections.OrderedDict()

    starting_and_end_days = []


    months = int(months)
    print months
    for month_count in range(months,0,-1):
        six_months = datetime.datetime.today() + relativedelta(months=-month_count)
        last_day_of_month = calendar.monthrange(six_months.year, six_months.month)[1]
        six_month = six_months.month

        if six_month != 10 and six_month != 11 and six_month != 12:
            six_month = "0" + str(six_month)

        sixth_months_first = str(six_months.year) + "-" + str(six_month) + "-" + "01"
        sixth_months_last = str(six_months.year) + "-" + str(six_month) + "-" + str(last_day_of_month)
        starting_and_end_days.append((sixth_months_first, sixth_months_last))

    months_dict = collections.OrderedDict()
    last_month_total = 0
    for first_day, last_day in starting_and_end_days:

        old_month = int(last_day.split("-")[1]) - 1
        if len(str(old_month)) < 2:
            old_month = "0" + str(old_month)

        #if str(last_day.split("-")[2]) == "28":
        #    first_day = last_day.split("-")[0] + "-" + old_month + "-31"
        #else:
        #    if str(last_day.split("-")[2]) == "30":
        #        first_day = last_day.split("-")[0] + "-" + old_month + "-31"
        #    else:
        #        first_day = last_day.split("-")[0] + "-" + old_month + "-30"

        one_month_forward = int(last_day.split("-")[1]) + 1

        if len(str(one_month_forward)) < 2:
            one_month_forward = "0" + str(one_month_forward)

        year = last_day.split("-")[0]

        if str(one_month_forward) == "01":
            year = int(year) + 1
            year = str(year)
        last_day = year + "-" + one_month_forward + "-01"

        cost_dict = get_aws_data(first_day, last_day)

        total_cost = 0.0

        time_frame = str(first_day) + ":" + str(last_day)
        if time_frame not in months_dict.keys():
            months_dict[time_frame] = {}

        for cost in cost_dict:
            if cost_dict[cost]["UnblendedCost"] >= 0.1:
                total_cost = cost_dict[cost]["UnblendedCost"] + total_cost
                last_month_total = total_cost

        dates_dict[first_day] = total_cost
        days = int(str(last_day).split("-")[2]) - int(str(first_day).split("-")[2]) + 1
        average_by_day = total_cost / float(days)

        months_dict[time_frame]["cost"] = {}
        months_dict[time_frame]["cost"] = cost_dict

        months_dict[time_frame]["total"] = {}
        months_dict[time_frame]["total"] = total_cost

        months_dict[time_frame]["average"] = {}
        months_dict[time_frame]["average"] = str(average_by_day)


    return dates_dict, months_dict, round(last_month_total, 2)

def generate_month_cost_report():

    todays_date = datetime.datetime.now()
    day = todays_date.day
    year = todays_date.year
    month = todays_date.month
    first_day = "01"

    if month != "10" and month != "11" and month != "12":
        first_date = str(year) + "-0" + str(month) + "-" + str(first_day)

        if len(str(day)) < 2:
            day = "0" + str(day)

        current_date = str(year) + "-0" + str(month) + "-" + str(day)
    else:
        first_date = str(year) + "-" + str(month) + "-" + str(first_day)

        if len(str(day)) < 2:
            day = "0" + str(day)

        current_date = str(year) + "-" + str(month) + "-" + str(day)

    cost_dict = get_aws_data(first_date, current_date)

    time_frame = str(first_date) + ":" + str(current_date)

    total_cost = 0.0

    for cost in cost_dict:
        if cost_dict[cost]["UnblendedCost"] >= 0.1:
            total_cost = cost_dict[cost]["UnblendedCost"] + total_cost

    average_by_day = total_cost / float(day)

    last_day_of_month = calendar.monthrange(datetime.datetime.now().year, datetime.datetime.now().month)[1]

    number_of_days_left_in_month = last_day_of_month - datetime.datetime.now().day

    total_left_for_month = average_by_day * number_of_days_left_in_month

    return cost_dict, total_left_for_month, total_cost, first_date, time_frame, average_by_day


class PDF(FPDF):
    def header(self):
        # Logo
        self.image('logo_pb.png', 10, 8, 33)
        # Arial bold 15
        self.set_font('Arial', 'BI', 10)
        # Move to the right
        self.cell(80)
        # Title
        self.cell(30, 10, 'Title', 0, 0, 'C')
        # Line break
        self.ln(20)

    # Page footer
    def footer(self):
        # Position at 1.5 cm from bottom
        self.set_y(-15)
        # Arial italic 8
        self.set_font('Arial', 'I', 8)
        # Page number
        self.cell(0, 10, 'Page ' + str(self.page_no()) + '/{nb}', 0, 0, 'C')

pdf = PDF()
pdf.alias_nb_pages()
pdf.add_page()

cost_dict, total_left_for_month, total_cost, first_date, time_frame_this_month, average_by_day = generate_month_cost_report()

predicted_total_cost = total_cost + total_left_for_month
predicted_total_cost = round(predicted_total_cost, 2)
predicted_total_cost_string = " $" + str(predicted_total_cost)

number_of_months = str(number_of_months).strip()
number_of_months = int(number_of_months)
dates_dict, months_dict, last_month_total = generate_monthly_cost_report(number_of_months)
dates_dict[first_date] = predicted_total_cost

plot_data = []
month_data = []

for item in dates_dict:
    plot_data.append(int(dates_dict[item]))
    year = str(item).split("-")[0]
    month = str(item).split("-")[1]
    month_item = month + "/" + year
    month_data.append(month_item)

#import time
#epoch_months = []
#for month in month_data:
#    pattern = '%Y-%m-%d'
#    epoch = int(time.mktime(time.strptime(month, pattern)))
#    epoch_months.append(epoch)

sns.set_style("darkgrid")
plt.xticks(rotation=20)
plt.plot(month_data,plot_data)
plt.savefig("cost-trend.png")

spacer_string = """
























"""
pdf.multi_cell(0, 5, spacer_string, 0, 1)

labels = []
sizes = []
colors = []

for cost in cost_dict:
    if cost_dict[cost]["UnblendedCost"] >= 0.1:
        labels.append(cost)
        sizes.append(int(cost_dict[cost]["UnblendedCost"]))

number_of_colors = len(sizes)
colors = []
color_choices = ['gold', 'yellowgreen', 'lightcoral', 'lightskyblue', 'yellowgreen', 'lightcoral', 'lightskyblue', 'purple', 'grey']
count = 0

for color in range(0,number_of_colors):
    colors.append(color_choices[count])
    count += 1

plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True, startangle=90)

plt.axis('equal')

plt.savefig("cost-pie2.png")


pdf.set_font('Times', 'B', 10)
pdf.image('cost-trend.png', 0, 30, 200, 120)

pdf.set_font('Times', 'B', 10)
pdf.cell(0,5, time_frame_this_month, 0, 1)
for cost in cost_dict:
    if cost_dict[cost]["UnblendedCost"] >= 0.1:

        pdf.set_font('Times', 'B', 10)
        cost_string = "     " + cost + ": "
        pdf.cell(80, 5, cost_string, 0, 0)

        pdf.set_font('Times', '', 10)
        cost_new_string = "$" + str(round(cost_dict[cost]["UnblendedCost"], 2)).strip()
        pdf.cell(40, 5, cost_new_string, 0, 1)

pdf.ln(5)
pdf.line(10, 30, 200, 30)
pdf.set_font('Times', 'B', 10)
cost_string = "Total: "
pdf.cell(80, 5, cost_string, 0, 0)

pdf.set_font('Times', '', 10)
total_cost_string = " $" + str(round(total_cost, 2))
pdf.cell(0, 5, total_cost_string, 0, 1)


pdf.set_font('Times', 'B', 10)
cost_string = "Predicted Total: "
pdf.cell(80, 5, cost_string, 0, 0)

pdf.set_font('Times', '', 10)
pdf.cell(0, 5, predicted_total_cost_string, 0, 1)


next_thirty_days = average_by_day * 30
next_thirty_days = " $" + str(round(next_thirty_days, 2))

pdf.set_font('Times', 'B', 10)
cost_string = "Predicted Total Next 30 Days: "
pdf.cell(80, 5, cost_string, 0, 0)

pdf.set_font('Times', '', 10)
pdf.cell(0, 5, str(next_thirty_days), 0, 1)

pdf.set_font('Times', 'B', 10)
cost_string = "Last Month Total: "
pdf.cell(80, 5, cost_string, 0, 0)

pdf.set_font('Times', '', 10)
pdf.cell(0, 5, " $"+str(last_month_total), 0, 1)

net_change = (last_month_total / predicted_total_cost) * 100
net_change = net_change - 100
net_change = abs(net_change)
net_change = round(net_change, 2)

pdf.set_font('Times', 'B', 10)
cost_string = "Net Change: "
pdf.cell(80, 5, cost_string, 0, 0)

pdf.set_font('Times', '', 10)
pdf.cell(0, 5, "  "+str(net_change) + "%", 0, 1)

pdf.ln(5)
pdf.set_font('Times', 'B', 10)
pdf.cell(0, 10, "Historical "+str(number_of_months)+" Month Cost Analysis", 0, 1)

for timeframe in sorted(months_dict, reverse=True):
    total_cost = 0.00
    time_frame = timeframe
    time_frame_string = timeframe

    pdf.set_font('Times', 'B', 10)
    pdf.cell(0, 5, time_frame_string, 0, 1)

    pdf.set_font('Times', '', 10)

    for cost in months_dict[timeframe]["cost"]:
        if months_dict[timeframe]["cost"][cost]["UnblendedCost"] >= 0.1:

            pdf.set_font('Times', 'B', 10)
            cost_string = "     " + cost + ": "
            pdf.cell(80, 5, cost_string, 0, 0)

            pdf.set_font('Times', '', 10)
            cost_string = " $" + str(round(months_dict[timeframe]["cost"][cost]["UnblendedCost"], 2)).strip()
            pdf.cell(0, 5, cost_string, 0, 1)

            months_dict[timeframe]["cost"][cost]["TimeFrame"] = time_frame
            total_cost = months_dict[timeframe]["cost"][cost]["UnblendedCost"] + total_cost

    pdf.ln(5)
    pdf.set_font('Times', 'B', 10)
    cost_string = "Total: "
    pdf.cell(80, 5, cost_string, 0, 0)

    pdf.set_font('Times', '', 10)
    total_cost_string = " $" + str(round(total_cost, 2))
    pdf.cell(0, 5, total_cost_string, 0, 1)
    pdf.ln(10)

pdf.cell(0, 10, "   ", 0, 1)
pdf.set_font('Arial', 'I', 8)
pdf.cell(5, 10, " * EC2 - Other: Cost not asscoiated with ELB or EC2 Instance. Examples would be: EBS volumes or Elastic IP addresses.", 0, 1)

pdf.output('AWSCost.pdf', 'F')
print "Report generated."


#better formatting
#trendline
#move the graphic to the top middle

1 Ответ

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

Я закончил тем, что нашел решение, это было добавить plt.close () перед созданием нового графика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...