오억년만에 나타나서 처음 쓰는 글은 pd.read_csv할 때 utf-8, utf-16, 심지어는 cp949까지도 오류날 때 해결하는 방법이다.

 

 

[python] 파이썬 공공데이터 csv 파일 읽어오기_인코딩 에러 해결

회사에서 진행하는 데이터분석 아카데미 프로젝트 마감이 얼마 남지 않았다. 데이터 수집은 다했는데 전처리가 관건일듯.. 공공데이터 포털사이트에서 다운받은 cvs 파일을 pandas 모듈을 이용해

javagirl.tistory.com

 

위의 블로그가 엄청 큰 도움이 됐는데, 걍 결론적으로 엑셀 파일을 csv로 저장할 때 애초에 인코딩을 utf-8로 하는것이었다.

 

엑셀에서 엄청 긴 숫자를 입력하면 얘가 자동적으로 숫자로 인식해서 막 16e+06 이런식으로 지멋대로 숫자로 변환하는데 그게 싫어서 full 숫자로 저장하게 하려고 csv로 저장해서 python에서 불러오는 걸 하려고 했었다.

 

내가 현재 일하고 있는 회사에서는 이런식으로 숫자가 엄청 길게 기재되는 경우가 매우 빈번해서 이런 아주 간단한 부분을 확실히 알고 넘어가야 했다.

 

엑셀을 csv로 저장할 때 인코딩 오류로 열리지 않을 때는 애초에 엑셀에서 엑셀 메뉴 > 파일 > 다른이름으로 저장 > 파일형식 : csv utf8(쉼표로분리)로 저장 하면 된다.

 

멍청한 나는 for문에 너무 집착한 나머지 1시간 동안 머리를 싸매다가 결국 Discuss를 보고 말았다.

while문이 무한루프를 도는 경우가 싫어서 왠만해선 for문을 써왔었는데 최근 Leetcode 문제들을 풀어보면 while이 그렇게 나쁜것도 아니고, 오히려 굉장히 실용적이라는 느낌도 들었다. 코딩문제를 풀때 while도 많이 애용해 봐야겠다고 생각했다.

 

 

 

 

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        MAX = 0 
        x = len(height) - 1
        y = 0
        while x != y:
            if height[x] > height[y]:
                area = height[y] * (x - y)
                y += 1
            else:
                area = height[x] * (x - y)
                x -= 1
            MAX = max(MAX, area)
        return MAX

 

이걸 for문으로 하려면 아주 난리를 쳐야했는데 만들면서도 굉장히 잘못됐다고 느꼈었다ㅋㅋㅋㅋ,,, while... 애용합시다!

 

 

 

 

 

 

킹갓 tqdm을 아는가? 나만 몰랐던 이야기라면 그건 좀 아쉽군...

 

tqdm

 

파이썬 반복문 어디까지 진행되었는지 표시하기: tqdm 라이브러리

반복문을 돌리면 작업이 어디까지 진행된 건지, 되고는 있는 건지 궁금할 때가 많이 있습니다. 주피터 노트북 화면을 바라보며 반복문을 돌린 셀의 별표가 사라지길 계속 기다리기도 조금 답답

hogni.tistory.com

 

for문에 tqdm을 사용하면 이 친구가 언제 다 돌아가는지 확인할 수 있어서 매우 유용하다. 

 

import fitz, os
import pandas as pd
from tqdm import tqdm

path_dir = './'
file_list = os.listdir(path_dir)
# print(file_list) # 현재폴더(./) 안에 있는 파일명들이 리스트화되어 들어가 있다.

for data in tqdm(file_list) :
    if '.pdf' in data :
        doc = fitz.open('./{}'.format(data))
        page = doc.loadPage(0)
        pix = page.getPixmap()
        output = "../pdf2png/{}.png".format(data.replace('.pdf',''))
        pix.writePNG(output)

그럼 이런식으로 볼 수 있음

 

따봉 tqdm아 고마워!

 

 

 

pdf2image라는 모듈이 있으나 poppler에서 계속 오류가 났던 나는 차선책을 찾게 되었는데, 속도 면에서는 얼마나 차이가 나는지는 모르겠지만 일단 내가 PyMuPDF를 사용해 본 결론으로는 굉장히 느리다ㅋㅋ... 코드도 느릴만하긴하지만.. 그래도 PyMuPDF는 원하는 PDF 페이지만을 선택해서 이미지화 할 수도 있기 때문에 나름 유용하다.

 

사실 pdf 파일을 이미지로 바꾸기만 하면 되는거 아니겠어? pdf2image모듈을 못 사용하니 꿩 대신 닭을 사용했다.

 

PyMuPDF

 

pymupdf/PyMuPDF

Python bindings for MuPDF's rendering library. Contribute to pymupdf/PyMuPDF development by creating an account on GitHub.

github.com

pip install -U pymupdf 를 한 후,

 

요 이미지대로 수행하면 png 파일로 나온다.

 

이 방식으로 png 파일로 만들 수 있는데, 이 png 파일을 jpg 파일로 바꾸고 싶다면... Pillow를 사용해도 될거같고 사실 걍 저 확장자만 바꿔줘도 될거같기도 하고.. (그렇다 png를 jpg로 바꿔주면 또 그렇게 잘 됨 굿 ^^)

암튼! 다들 pdf2image에 고생하지 말고 나처럼 꿩대신 닭으로도 도움 얻길!

 

 

 

대부분의 사람들이 그렇겠지만, 개인적으로 굉장히 어려워하는게 Node인데 하필이면 2번부터 Node가 나왔다ㅋㅋㅋ 번호 순서대로 풀지 말아야겠다는 생각이 강력하게 들었지만 의외로 또 문제가 쉬워보여서 도전해봤다. 어렵진 않았지만 Node의 개념을 모른다면 절대 못푸는 그런 문제... return값도 node라는게 아주 키포인트임!

 

 

 

 

 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

# 내 풀이
class Solution:
    def addTwoNumbers(self, l1, l2):
        # print(l1.next.next) # ListNode{val: 3, next: None}
        # ListNode는 길이가 없다. 생각해보면 당연하지만 일단 len충인 나는 해봤다 봉변당함ㅋㅋ
        # print(len(l1)) # 'ListNode' has no len()

        result = 0
        i = 0
        
        # 우선 l1과 l2에 있는 데이터로 연산을 완료 (result)
        while l1 or l2 :
            if l1 != None :
                result += l1.val*(10**i)
                l1 = l1.next
            if l2 != None :
                result += l2.val*(10**i)
                l2 = l2.next
            i += 1
            
        # for문을 돌리기 위해 int인 result를 str로 변경한 모습 (별로 좋다고 생각은 안함)
        result = str(result)
        # 여기서 진짜 웃긴게 cur을 사용하지 않으면 node가 제대로 이어지지 않는다.
        answer = cur = ListNode(0)
		
        # answer = cur = ListNode(0)이 아니고
        # answer = ListNode(0)으로 해서 아래 for문을 cur 대신 answer쓰면 제대로 node 형성이 안됨
        for i in range(len(result)-1,-1,-1) :
            cur.next = ListNode(result[i])
            cur = cur.next
            
        # return도 제법 웃겨
        return answer.next

 

속도 암담하다.. 아마 node 만들때 for문 쓴게 크지 않을까 하는 마음
근데 같은 코드인데 제출할때마다 바뀌는거 보면 크게 신경 안써도 될것도 같고...

 

 

# Discuss에서 추천 수 많았던 코드

class Solution:
    def addTwoNumbers(self, l1, l2):
        carry = 0
        root = n = ListNode(0)
        while l1 or l2 or carry:
            v1 = v2 = 0
            if l1:
                v1 = l1.val
                l1 = l1.next
            if l2:
                v2 = l2.val
                l2 = l2.next
            # print(carry)
            # print("v1 :",v1,"v2 :",v2)
            carry, val = divmod(v1+v2+carry, 10)
            # print(carry,val)
            n.next = ListNode(val)
            n = n.next
        return root.next

위의 코드를 보면 결국에 나랑 비슷한 생각인데 나는 올림에 대해 어떻게 해야할지 모르겠어서 연산을 다 마치고 연산이 끝난 데이터를 역순으로 뽑아 node를 만들었다면, 이 사람은 한번에 node까지 만든것을 볼 수 있다. 올림을 저렇게 할 생각을 못했었는데 진짜 똑똑한것 같다.

 

속도면에서는 굉장히 앞도적으로 빠르다

 

이 부분에 대해서는 조금 더 공부한 내용을 추가하도록 하겠다! Node를 아주 부셔버리겠어...

 

 

+ Recent posts