본문 바로가기

WIL (Weekly I Learned)

[WIL] 2021년 9월 넷째 주/ 10월 첫째 주 WIL

9월 넷째 주의 절반은 추석과 함께 실종되어버렸다.

그리하여.. 9월 넷째 주 WIL은 아래 세 게시글로 스무스하게 대체하려고 한다.

 

[Python] Beutiful Soup4 - decompose() 와 extract()

[Spark] SQL - explode()를 사용하여 list 형태의 Row 분리하기

[Spark] SQL - 두 컬럼을 병합하여 새로운 Dataframe 만들기

 

📝 10월 5일 (화)

▪️NLP - Word2Vec

모델 Load 시 UnicodeDecodeError

UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte

해결

KeyedVectors.load_word2vec_format()Word2Vec.load() 로 수정

 

Ref

https://github.com/Kyubyong/wordvectors/issues/12

 

 

 

📝 10월 6일 (수)

▪️git

이미 Push한 커밋 메세지 수정하기

$ git commit --amend -m "수정된 메세지"
$ git push --force

 

▪️Spark SQL

Hdfs에 text를 Dataframe형식으로 저장하기

spark session생성

from pyspark.sql import SparkSession 

spark = SparkSession.getOrCreate()

list형태로 string 저장

record_txt = []
record_txt.append(f"First Sentence.")
record_txt.append(f"Second Sentence.")
record_txt.append(f"Third Sentence.")
record_txt.append(f"Fourth Sentence.")

pandas를 이용하여 DataFrame 생성

record_df = pd.DataFrame(record_txt, columns=["text"])

데이터에 record_txt, 컬럼명은 text로 지정하였다.

 

 

주의할 점은 반드시 데이터 타입으로 list 가 들어가야한다. record_txt 가 string type일 경우 에러가 난다.

 

spark DataFrame 생성 후 text format으로 저장

 

spark에 데이터프레임을 생성할때 저장하는 데이터에 대한 스키마 정보가 필요하다.

schema = StructType(
           [StructField("text", StringType(), True)])
records = spark.createDataFrame(record_df, schema).coalesce(1)
records.write.format("text").mode("overwrite").save(save_path)

 

 

 

📝 10월 7일 (목)

▪️Linux

nohup 백그라운드 실행 종료시키기

실행중인 프로세스 확인

$ jobs

kill 명령어로 종료

$ kill %1

Ref.

http://egloos.zum.com/tmt313/v/400132

 

 

📝 10월 8일 (금)

▪️Hadoop

HDFS 파일 삭제 커맨드

폴더 내의 파일 목록 확인

$ hdfs dfs -ls 폴더 경로

특정 파일 삭제

$ hdfs dfs -rm -R 파일위치

 

 

 

📝 10월 9일 (토)

▪️Python

클래스 메소드 @classmethod

 

파이썬에서 메서드는 크게 세 가지로 나뉜다.

 

  1. 인스턴스 메서드 (instance method)
  2. 정적 메서드 (static method)
  3. 클래스 메서드 (class method)

 

인스턴스 메서드

 

인스턴스 메서드는 첫 번째 파라미터로 self 를 갖는 메서드. 하나의 클래스로부터 여러 객체 인스턴스를 생성 가능하고, self.변수명으로 인스턴스 변수에 접근 가능

 

Python 클래스는 기본적으로 모든 멤버가 public이다.

 

public, protected, private 등의 접근 제한자를 갖지 않기 때문에 코딩 관례상 내부적으로만 사용하는 변수나 메서드는 이름 앞에 하나의 밑줄 (_)을 붙인다.

특정 변수명이나 메서드를 private으로 만들어야한다면 두 개의 밑줄 (__)을 붙인다.

클래스 선언시 가장 먼저 적는 __init__ 메서드는 Initialzer이다.

 

 

 

 

 

정적 메서드

 

self파라미터를 갖지 않기때문에 인스턴스 변수에 엑세스 불가능.

보통 객체 필드와 독립적이지만 로직상 클래스내에 포함되는 메서드에 사용한다.

@staticmethod 데코레이터를 사용한다.

 

 

 

클래스 메서드

 

self 대신 cls 파라미터를 갖는 메서드. 정적메서드와 비슷한데 다른점은 cls 파라미터를 통해 클래스 변수 등을 엑세스 할 수 있다. 클래스 메서드는 인스턴스 생성 없이 호출이 가능하므로 클래스 메서드가 호출 되었을 때 인스턴스가 존재하지 않을 수도 있다.

class Figure:
    @classmethod
    def set_name(cls, name):
        cls.name = name

Figure.set_name("figure")
print(Figure.name) # 결과값 : figure figure

 

 

정리

  • 인스턴스 데이터에 접근할 필요가 없다면 ⇒ class method / static method 사용
  • 클래스 변수에 접근할 필요가 있다면 ⇒ class method
  • 클래스 변수에 접근할 필요가 없다면 ⇒ static method

Ref.

https://frenchkebab.tistory.com/56

https://journeytosth.tistory.com/73

 

 

 

📝 10월 10일 (일)

▪️Python

사용자 정의 hash 함수를 이용하여 데이터 중복 제거

 

set을 사용하여 중복을 제거할 수 없는 경우

list타입의 데이터의 경우 set 을 적용하면 데이터의 중복을 바로 제거할 수 있지만 여러개의 필드가 있는 직접 정의한 데이터 타입의 경우 set에 넣으면 unhashble type 에러가 뜨게 된다.

print(set(wiki_entities))

TypeError: unhashable type: 'MetaSourcedEntity'

Hashable

hashable 이라는 것은 어떤 데이터를 hash 함수를 이용해서 hash 값으로 변환할 수 있다는 것을 의미한다.

Hash란?

데이터를 알고리즘에 의해 암호화하는 것. 해쉬를 가지고 원래의 데이터를 복원하기 어렵기 때문에 해쉬화 된 값으로 두 데이터를 비교한다.

해결 방법

나는 Entity라는 자체적인 데이터 클래스를 정의한 다음, Entity객체들의 list인 EntitySet이라는 클래스를 정의하였다.

이 상황에서 EntitySet을 중복없는 Entity들의 list로 만들고자 하였다.

나 같은 경우에는 정의한 데이터 클래스 내에 두 개의 함수를 선언하였다.

 

 

 

Entity 클래스

  1. hash값을 부여하는 함수
  2. 두 개의 객체가 같은 hash값을 가지는지 검사하는 함수
@dataclass
class Entity:
    entity: str # 엔티티의 이름 
    def __hash__(self):
        text = self.entity
        return hash_func(text)

    def __eq__(self,other):
        return other.__hash__() == self.__hash__()

 

 

EntitySet 클래스

그리고 EntitySet 내에 중복을 제거하는 함수를 선언하여 로직을 구성하였다.

unique한 엔티티 리스트에 첫 번째 엔티티를 넣어 시작하고, 후보가 되는 엔티티를 모두 돌면서 unique 엔티티 내의 원소와 같은지 비교, 같지 않으면 추가하도록 하였다.

class EntitySet:
    def __init__(self, entities: List[Entity]):
        self.entities = entities
        self.distinct()

        def distinct(self):
        # initialize
        self.sort()
        unique_entities = [self.entities[0]]
        for ent in self.entities:
            unique = True
            for u_ent in unique_entities:
                if ent.__eq__(u_ent):
                    unique = False
                    break
            if unique:
                unique_entities.append(ent)

        self.entities = unique_entities 

 

 

Ref.

https://dog-foot-story.tistory.com/entry/자료구조-01-hash-hashSet-중복-제거

https://frhyme.github.io/python-basic/python_make_set_of_lst/

 

 

▪️boj 알고리즘

4948_베르트랑 공준

특정 수가 약수를 가졌는지 판단하기 위해서는 해당 수의 제곱근+1까지만 판단하면 된다.

입력받은 수의 제곱근까지 반복문을 돌며 확인한 코드는 시간초과가 나버렸다.

 

시간초과 코드

def count_prime(num):
    cnt = 0
    for x in range(num+1,2*num+1):
        if x <= 1: 
            continue
        for j in range(2, int(x ** 1/2)+1):
            if x % j == 0: break
        else:
            cnt += 1

    return cnt    

if __name__=="__main__":
    while True:
        n = int(input())
        if n==0:
            break
        print(count_prime(n))

소수를 찾는 알고리즘인 에라토스의 체를 이용하였다. 전체 수 중에서 소수가 아닌수를 지워나가는 방식이며, 2부터 시작해서 특정 숫자의 배수에 해당하는 숫자들을 모두 지우면 된다.

 

 

에라토스의 체를 이용한 코드

def eratos_prime_list(n):
    eratos = [1] * (2 * n + 1)
    eratos[0] = 0
    eratos[1] = 0
    for i in range(2, int(len(eratos) ** 1/2)+1):
        if eratos[i]==1:
            # i의 배수를 모두 제외
            for j in range(i + i, len(eratos), i):
                eratos[j] = 0

    return eratos

if __name__=="__main__":
    while True:
        n = int(input())
        if n==0:
            break
        eratos = eratos_prime_list(n)
        print(sum(eratos[n+1:(2*n)+1]))