파이썬(Python)

파이썬 엑셀 파일 읽어서 그래프 이미지(img)파일로 만들기

끄적끄적아무거나 2021. 8. 21. 09:13
반응형

파이썬 엑셀 파일 읽어서 그래프 이미지(img)파일로 만들기

 

이번 프로젝트는 python으로 엑셀 파일에 데이터들을 불러와서 해당 데이터들로 bar graph를 만들어야 하는 일이 었다. 우선 프로젝트 진행 사항은 아래와 같이 정리하였다.

 

  1. openpyxl 로 excel 파일안의 데이터를 5줄씩 가져오기
  2. 가져온 데이터를 리스트와 딕셔너리에 저장하기
  3. 데이터를 바(bar) 그래프 만드는 클래스 만들기
  4. 5줄의 데이터로 그래프를 만들어서 파일로 저장하기
  5. 다시 엑셀의 그 다음 5줄 데이터를 불러오기
  6. 앞서 동작을 데이터가 없을 때까지 진행하기

 


엑셀파일>> 임의의 값들로 채웠다.

 

코드>>

본인 컴퓨터에서 복사해서 실행을 하고 싶다면 주의할 점은 엑셀 파일 위치 경로를 변경해야한다.

import matplotlib.pyplot as plt
import numpy as np

class making_bar:
    def __init__(self, models, xticks, data, y_lim_min, y_lim_max, pic_no, x_label, y_label, title):
        self.models = models
        self.xticks = xticks
        self.data = data
        self.y_lim_min = y_lim_min
        self.y_lim_max = y_lim_max
        self.pic_no = pic_no
        self.x_label = x_label
        self.y_label = y_label
        self.title = title

    def main(self):
        self.fig, self.ax = plt.subplots(1,1,figsize=(11,8)) 
        colors = ['salmon', 'orange', 'cadetblue', 'skyblue', 'blue']
        hatch = ['/', '\\', '+', '*', 'o']
        width = 0.15

        n = len(self.models)
        for i, model in enumerate(self.models):
            index = np.arange(len(self.xticks))
            correction = i-0.5*(n-1)
            pos = index + width*correction
            self.bar = self.ax.bar(pos, self.data[model], width=width*0.95, label=model, color=colors[i], hatch=hatch[i])
            for rect in self.bar:
                height = rect.get_height()
                posx = rect.get_x()+rect.get_width()*0.5
                posy = height*1.02
                if height <= 0:
                    posy = 0.1
                self.ax.text(posx, posy, '%.2f' %height, rotation=90, ha='center', va='bottom')


        self.ax.set_xticks(range(len(self.xticks)))
        self.ax.set_xticklabels(self.xticks, fontsize=10)	
        self.ax.set_xlabel(self.x_label, fontsize=14)

        self.ax.set_ylim([self.y_lim_min,self.y_lim_max])
        self.ax.yaxis.set_tick_params(labelsize=10)
        self.ax.set_ylabel(self.y_label, fontsize=14)

        self.ax.legend(loc='upper left', shadow=True, ncol=1)

        self.ax.set_axisbelow(True)
        self.ax.yaxis.grid(True, color='gray', linestyle='dashed', linewidth=0.5)

        plt.title(self.title, fontsize=20)
        plt.tight_layout()
        plt.savefig('result'+str(self.pic_no)+'.png', format='png', dpi=300)
        # plt.show()


models = ['Bar A', 'Bar B', 'Bar C', 'Bar D', 'Bar E']
xticks = ['xtick A', 'xtick B', 'xtick C', 'xtick D', 'xtick E']
data = {'Bar A':[0.65, 0.71, 0.69, 0.69, 0.69],
        'Bar B':[0.61, 0.65, 0.64, 0.69, 0.69],
        'Bar C':[0.55, 0.66, 0.60, 0.69, 0.69],
        'Bar D':[0.60, 0.62, 0.57, 0.69, 0.69],
        'Bar E':[0.60, 0.62, 0.57, 0.69, 0.69]}

from openpyxl import load_workbook
try:
    wb = load_workbook(r"C:\Users\forgo\Documents\data.xlsx")
    ws = wb.active
except:
    print("Failed to read excel file")


##Init##
x_min = 2
x_max = 7
y_lim_min = 0
y_lim_max = 5
pic_no = 0
data = {}
models = []
cell_data = []
xticks = []

title = input("Enter bar graph title(If don't want, press ENTER) :")
x_label = input("Enter x label name(If don't want, press ENTER) :")
y_label = input("Enter y label name(If don't want, press ENTER) :")

for y in range(2, 7):
    xticks.append(ws.cell(row=1, column=y).value)

while (x_max <= ws.max_row+5):
    for x in range(x_min, x_max):
        for y in range(2, 7):
            raw_data = ws.cell(row=x, column=y).value
            if raw_data:
                cell_data.append(raw_data)
                if y_lim_max < raw_data:
                    y_lim_max = raw_data
                if y_lim_min > raw_data:
                    y_lim_min = raw_data
        if raw_data:
            data.update({ws.cell(row=x, column=1).value:cell_data})
            models.append(ws.cell(row=x, column=1).value)
        cell_data = []
    making_bar_1 = making_bar(models, xticks, data, y_lim_min+y_lim_min/8, y_lim_max+y_lim_max/8, pic_no, x_label, y_label, title)
    making_bar_1.main() 
    x_min = x_min + 5
    x_max = x_max + 5
    pic_no = pic_no + 1
    data = {}
    models = []


print("img file generation completed...")

 

결과>> 아래와 같이 입력하였다.

Enter bar graph title(If don't want, press ENTER) :My Bar Graph
Enter x label name(If don't want, press ENTER) :Cities
Enter y label name(If don't want, press ENTER) :
img file generation completed...

아래 그림처럼 2개의 이미지파일(png)이 만들어 졌다. 엑셀에 데이터가 총 9줄이라서 9/5 = 2개의 파일이 형성되었다.

 

아래 그림은 result0.png 의 그림이다. Title과 X 라벨에 값을 입력해서 아래처럼 만들어 졌다. Y라벨은 입력하지 않았다. 범례도 왼쪽 위에 바를 설명하게 놔두었다. 그리고 바 그래프에 색깔 뿐만 아니라 격자 무늬도 넣어서 명확하게 구분 가도록 만들었다.

 

 

반응형