본문 바로가기
웹 개발 실습/Django

[Django]_엑셀 계산 사이트 만들기 (5) 파일 업로드 및 분석

by ssolLEE 2023. 8. 2.
반응형

이 프로젝트도 마찬가지로 책 'Django 한 그릇 뚝딱'의 Chapter 4을 보며 실행해보았습니다. 책의 저자님께 다시 한 번 감사말씀 드립니다.

 

오늘은 드디어 파일을 업로드하고 읽어보겠습니다.

 

파일 업로드하기

우리에게 필요한 프로세스는 파일 업로드 / 계산 / 결과 화면 보여주기 가 있습니다.

 

  • ExcelCalculate > main > templates > main > index.html 로 이동합니다. 
  • 41번째 줄을 다음과 같이 수정합니다.

  • ExcelCalculate  > ExcelCalculate > urls.py 로 이동하여 path를 추가해야 하지만 편의상 우리는 이미 했습니다. 흐름을 파악하기 위해 그래도 확인하고 갑시다.

  • ExcelCalculate > calculate > urls.py 에 작성한 것을 확인합니다.
  • ExcelCalculate > calculate > views.py 에서 사용자 정의 함수를 구현합니다.
def calculate(request):
    file = request.FILES['fileInput']
    print("# 사용자가 등록한 파일의 이름: ", file)
    return HttpResponse("calculate, calculate function!")

웹 서버로 파일이 정상적으로 넘어왔다.

 

엑셀 파일 분석하기 (using Pandas) - grade별 value 구하기

 

우리는 책의 저자가 제공한 data.xlsx을 Pandas 라이브러리를 이용하여 다음의 값을 구해보겠습니다.

  • grade별 value 최솟값, 최댓값, 평균값
  • 이메일 도메인 주소별 인원수 
  • ExcelCalculate > calculate > views.py 에서 파일 불러오도록 코드를 작성합니다.

  • 웹 페이지에서 '파일 제출'을 누르면 terminal에 다음과 같이 출력이 됩니다.

  • grade별 value리스트를 만들어보겠습니다. calculate 함수에 계속 이어서 작성합니다.
grade_dic = {} # 빈 딕셔너리 생성
total_row_num = len(df.index)
print(total_row_num)

전체 행의 개수는 100이다.

  • 조건문을 추가합니다. 진행상황 확인 차 print()는 적절히 넣고 삭제합니다.(또는 주석처리)
  • 이 문법은 책의 것과 다릅니다. 책은 2019년도 출판으로 버전이 달라져서 문법이 달라졌습니다.
for i in range(total_row_num):
        data = df.loc[i, :]
        print(data)
        print("")
        print("")

Name: 0~99까지 100개 출력됩니다.

  • 이렇게 출력된 결과물은 Series일까요? DataFrame일까요?

Series입니다.

    •  이렇게 조건문을 구성하면서 모든 데이터에 대해서 grade별 value값이 grade_dic에 저장됩니다. 
if not data['grade'] in grade_dic.keys():
	 grade_dic[data.grade] = [data.value]
else:
	grade_dic[data.grade].append(data.value)
print(grade_dic)
  • 이제 grade별 최솟값, 최댓값, 평균값을 구하고 저장하기 위해 grade_calculate_dic이라는 딕셔너리형 변수를 선언하겠습니다.
    grade_calculate_dic = {}
    for key in grade_dic.keys():
        grade_calculate_dic[key] = {}
        grade_calculate_dic[key]['min'] = min(grade_dic[key]) # 각 grade별 최솟값 
        grade_calculate_dic[key]['max'] = max(grade_dic[key]) # 각 grade별 최댓값
        grade_calculate_dic[key]['avg'] = float(sum(grade_dic[key])) / len(grade_dic[key])
    
    print(grade_calculate_dic)
  • 저장한 값들을 출력하는 코드를 입력하겠습니다. 코드를 한 줄 한 줄 print()하며 분해해보면 공부에 큰 도움이 될 것입니다.
	# 결과 출력
    grade_list = list(grade_calculate_dic.keys())
    # print("")
    # print(grade_list)
    grade_list.sort()
    # print(grade_list)
    for key in grade_list:
        print("# grade: ", key)
        print("min:", grade_calculate_dic[key]['min'], end="")
        print("/ max:", grade_calculate_dic[key]['max'], end="")
        print("/ avg:", grade_calculate_dic[key]['avg'], end="\n\n")

 

 

엑셀 파일 분석하기 (using Pandas) - 이메일 주소 도메인별 인원 구하기

 

  • 코드는 위에서 작성하는 calculate 함수에 계속 이어서 작성합니다.
    email_domain_dic = {}
    for i in range(total_row_num):
        data = df.loc[i, :]
        print(data.email)
        email_domain = data['email'].split("@")[1]
        if not email_domain in email_domain_dic.keys():
            email_domain_dic[email_domain] =1 # 새로운 도메인이 나타나면 숫자 1 부여
        else:
            email_domain_dic[email_domain] += 1 # 기존 도메인이 또 나타나면 +1 추가
            
        print("## Email 도메인 별 사용 인원")
        for key in email_domain_dic.keys():
            print("#", key, ":", email_domain_dic[key], "명")

 

 

엑셀 파일 분석하기 (using Pandas) - 조금 더 간편한 코드

  • 위의 긴 코드를 조금 더 간편하게 작성하고자 합니다. 
  • 코드의 출처는 정지훈 강사님(블로그: Data Science | DSChloe)입니다.
# grade_df = df.groupby('grade')['value'].agg(["min", "max", "mean"]).reset_index().rename(columns = {"mean" : "avg"})
# print(grade_df)
# print("")
# df['domain'] = df['email'].apply(lambda x : x.split("@")[1])
# email_df = df.groupby('domain')['value'].agg("count").sort_values(ascending=False).reset_index()
# print(email_df)

 

감사합니다.