pandas에서 필터링 방법을 여쭙습니다

조회수 682회

안녕하세요 파이썬을 통해 자연어 처리(khaiii 활용)를 해서 아래와 같은 결과값을 도출했습니다.

import numpy as np
import pandas as pd
from khaiii import KhaiiiApi
api = KhaiiiApi()

df = pd.read_csv('president.csv', encoding = 'utf-8')
df = pd.DataFrame(df)

df['내용'] = df["내용"].str.replace(",", "") 

split = df.내용.str.split(".")
split = split.apply(lambda x: pd.Series(x))
split = split.stack().reset_index(level=1, drop=True).to_frame('sentences')
df = df.merge(split, left_index=True, right_index=True, how='left')
df = df.drop(['내용'], axis = 1)
df['sentences'].replace('', np.nan, inplace= True)  
df['sentences'].replace(' ', np.nan, inplace= True)
df.dropna(subset=['sentences'], inplace=True)
df = df.reset_index(drop=True) 

nlp = df.sentences.apply(lambda x: [str(w).split('\t')[1] for w in api.analyze(x)])

이미지

제가 하고 싶은 것은 뒤에 nlp 열에 있는 nng, vv, va로 태그된 단어 만을 추출하고 싶은데 아직 python 사용이 어려워 질문을 드립니다.

예를 들어 nlp의 첫 열을 기준으로

[젊(다), 때, 중소기업, 사장, 하(다)]

의 형태로 정제하고 싶습니다.

추가로 vv와 va 뒤에는 '다'를 붙여서 완전한 형태로 만들고 싶은데 방법을 알려주시면 너무나 감사하겠습니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

4 답변

  • 저는 복습겸 학습겸 하는 것이지만 제가 이렇게 하는 것이 질문자께 무슨 도움이 될지는 모르겠습니다.

    현재 임베딩시 많이 사용하는 word2vec 을 이용한 샘플입니다.

    모델은 skip gram 을 사용했습니다.

    import itertools as it
    import pandas as pd
    
    from khaiii import KhaiiiApi
    
    df = pd.read_csv('https://drive.google.com/u/0/uc?id=1IZ1NYJmbabv6Xo7WJeqRcDFl1Z5pumni&export=download')
    df.drop(columns=['NO', '대통령', '날짜'], inplace=True)
    
    api = KhaiiiApi()
    
    def parse(sentence):
        pos = ((morph.lex, morph.tag) for word in api.analyze(sentence) for morph in word.morphs if morph.tag in ['NNG', 'VV', 'VA'])    # only nng, vv, va
        words = [item[0] if item[1] == 'NNG' else f'{item[0]}다' for item in pos]  # append suffix
        return words
    
    df['nlp'] = df['내용'].apply(parse)
    
    from gensim.models.word2vec import Word2Vec
    
    model = Word2Vec(df['nlp'].values, sg=1, window=5, min_count=1, workers=4, iter=100) 
    model.init_sims(replace=True)
    
    print(model.wv.similarity('젊다','사장'))
    
    print(model.wv.similarity('젊다','중소기업'))
    
    # 빈도수
    from collections import Counter
    df['cnt'] = df['nlp'].apply(lambda words:dict(Counter(words)))
    
    
    
    • 선생님, 너무 감사드립니다. 주신 코드로 계속 공부하고 있고, 응용은 못하지만 적용하고 있습니다. 제가 사이트가 처음이라 채택 기능이 있는걸 몰랐네요. 귀중한 시간 할애해주셔서 너무 고맙습니다. 알 수 없는 사용자 2020.2.3 10:03
    • 한 가지 더 여쭙고 싶은게 있는데 만들어 주신 parse 함수는 명사, 동사, 형용사 순으로 정렬이 되는데, 혹시 정렬 기능을 제거를 하려면 어떻게 해야 하는지 알 수 있을까요? 알 수 없는 사용자 2020.2.3 11:29
    • 정렬을 일부로 했어요(sorted 함수) 파이썬의 groupby 함수를 이용하려면 같은 것 끼리 나열되어 있을때 가능하기에 정렬을 한 것인데...groupby 를 제거하면 코드가 길어지겠지요. 정영훈 2020.2.3 11:43
    • 아.. 간단한 문제가 아니었네요 ㅠㅠ 염치없고 죄송하지만 혹시 정렬 기능만 제거해주실 수 있을까요? 알 수 없는 사용자 2020.2.3 12:07
    • 아....생각해보니 단어 위치를 변경하면 안되겠네요. 빈도수로 계산하는 것이 아니라 window 로 하기 때문에 위치가 바뀌면 안되요-.- 제가 단순히 품사 분류만 생각했군요. 정영훈 2020.2.3 12:13
    • 코드에서 grouping 을 제거해서 더 단순해지긴 했네요. 용도를 몰랐을때는 품사별로 grouping 을 진행했는데 용도가 임베딩이라면 필요없겠네요. 정영훈 2020.2.3 12:20
    • 제가 설명을 잘해드렸어야 됐는데 그러지 못해서 여러 번 도움을 받게 되었네요. 정말 감사합니다. 알 수 없는 사용자 2020.2.3 13:06
    • 혹시 질문을 더 드려도 괜찮을까요? nlp열에서 나타난 단어들의 빈도 수를 확인하려면 어떻게 해야 하나요? 알 수 없는 사용자 2020.2.5 02:41
    • from collections import Counter // Counter(df.nlp.str.split(",")) 으로 해봤는데 저는 잘 안되네요. 알 수 없는 사용자 2020.2.5 02:43
    • Counter 는 맞게 사용하셨는데 apply 로 각 벡터당 연산을 해줘야 합니다. 정영훈 2020.2.5 11:43
    • 아!! 감사합니다.. 또 해보겠습니다.. 알 수 없는 사용자 2020.2.5 13:02
  • president.csv 파일도 올려주지 않았고 khaiii 는 현재 장비에 설치되어 있지 않은 관계로 konlpy 로 해봅니다.

    또한 위와 같은 csv 파일이면 차라리 '내용'만 추출하고 하나의 텍스트를 다루는 편이 낫습니다.

    • 문재인대통령취임연설문.txt

    https://drive.google.com/open?id=1_wuhj7bzI10iekt_uW1_tEOGXEJY2fVR

    import itertools as it
    from konlpy.tag import Kkma
    
    with open('문재인대통령취임연설문.txt', encoding='euc-kr') as f:
        contents = f.read().splitlines()[0]
    
    kkma = Kkma()
    morph = kkma.pos(contents)  # 형태소분석
    groups = {word: set(i[0] for i in tag) for word, tag in it.groupby(sorted(morph, key=lambda item:item[1]), lambda item:item[1])} # 품사별로 분류(중복제거함)
    
    print(groups['NNG'])
    # {'첫걸음', '제', '국민', '머리', '경험', '열정', '감사', '오늘', '대통령', '존경', '어깨', '세상', '공존', '선택', '대한민국', '한번', '사랑', '가슴', '통합', '청사진', '나라', '소명감'}
    print(groups['VV'])
    # {'차', '향하', '숙이', '내딛', '부여받', '드리', '만들', '열', '갈'}
    print([f'{word}다' for word in groups['VV']])
    # ['차다', '향하다', '숙이다', '내딛다', '부여받다', '드리다', '만들다', '열다', '갈다']
    
    • 답변 정말 감사합니다. 저는 단어 간 거리를 측정해야 해서 문장 단위로 먼저 분류하였습니다. 귀중한 시간 할애해 주셔서 감사합니다. 만들어주신 코드로 응용해보겠습니다 알 수 없는 사용자 2020.2.2 10:00
  • 인덱스 제거나 컬럼명 변경은 하지 않았습니다.

    import itertools as it
    import pandas as pd
    
    from konlpy.tag import Kkma
    
    df = pd.read_csv('https://drive.google.com/u/0/uc?id=1IZ1NYJmbabv6Xo7WJeqRcDFl1Z5pumni&export=download')
    df.drop(columns=['NO', '대통령', '날짜'], inplace=True)
    
    kkma = Kkma()
    
    def parse(sentence):   
        groups = {word: set(i[0] for i in tag) 
                  for word, tag in it.groupby(sorted(kkma.pos(sentence), key=lambda item:item[1]), lambda item:item[1])} # 품사별로 분류(중복제거함)
        return [*groups.get('NNG', []), *[f'{word}다' for word in groups.get('VV', [])], *[f'{word}다' for word in groups.get('VA', [])]]
    
    df['nlp'] = df['내용'].apply(parse)
    
    print(df['nlp'][0])
    ['신문사', '조기', '부가', '전날', '집약적', '생산', '질문', '달러', '은행', '정부', '금융', '수출', '소량', '소품종', '중소기업', '대출', '일거리', '시대', '가치', '지금', '장래', '피', '말', '기업', '기관', '사용', '대기업', '방안', '계획', '연장', '주택', '콜', '계산', '문제', '현장', '이하', '일자리', '어음', '업계', '일', '다품종', '선', '차이', '중요', '벤처', '표', '고충', '도산', '과거', '요즘', '달', '핵심', '수출입', '동안', '내력', '돈', '저녁', '우리나라', '실업자', '세기', '지방', '만기', '기금', '증가', '지원', '남', '신용', '기술', '노력', '금리', '해운업', '예산', '실업', '적극', '때', '정도', '사장', '집행', '산하', '보증', '회사채', '창구', '독려', '대량', '일선', '밀다', '보내오다', '저다', '있다', '쏟다', '가다', '돌아오다', '생기다', '살리다', '안되다', '대하다', '주다', '내리다', '말리다', '늘리다', '늘다', '내려오다', '알다', '잘하다', '위하다', '나다', '만들다', '벌다', '말씀하다', '잘되다', '이루어지다', '하다', '비싸다', '보다', '좋다', '안타깝다', '어떻다', '젊다', '같다', '이렇다']
    
    • 신경쓰고 고민해 주신 점 너무나도 감사합니다. 주신 코드 잘 응용해보겠습니다 알 수 없는 사용자 2020.2.2 11:35
  • khaiii 설치된 장비에서 확인후 올려드립니다.(두줄 변경되었네요)

    import itertools as it
    import pandas as pd
    
    from khaiii import KhaiiiApi
    
    df = pd.read_csv('https://drive.google.com/u/0/uc?id=1IZ1NYJmbabv6Xo7WJeqRcDFl1Z5pumni&export=download')
    df.drop(columns=['NO', '대통령', '날짜'], inplace=True)
    
    api = KhaiiiApi()
    
    def parse(sentence):
        pos = ((morph.lex, morph.tag) for word in api.analyze(sentence) for morph in word.morphs)
        groups = {word: set(i[0] for i in tag) 
                  for word, tag in it.groupby(sorted(pos, key=lambda item:item[1]), lambda item:item[1])} # 품사별로 분류(중복제거함)
        return [*groups.get('NNG', []), *[f'{word}다' for word in groups.get('VV', [])], *[f'{word}다' for word in groups.get('VA', [])]]
    
    df['nlp'] = df['내용'].apply(parse)
    
    print(df['nlp'][0])
    ['일자리', '소량', '장래', '기금', '주택', '생산', '사용', '해운업', '우리나라', '대량', '동안', '요즘', '집행', '중요', '기업', '이하', '대출', '수출입', '금융', '계획', '부가', '지원', '세기', '현장', '신용', '질문', '어음', '업계', '금리', '차이', '독려', '고충', '내력', '신문사', '남', '피', '조기', '기', '핵심', '전날', '집약', '창구', '기술', '정부', '회사채', '벤처', '품종', '중소', '기관', '실업', '가치', '적극', '다품종', '만기어음', '은행', '실업자', '선', '노력', '일', '정도', '문제', '예산', '과거', '일거리', '말', '방안', '지방', '중소기업', '도산', '일선', '돈', '말씀', '때', '연장', '계산', '수출', '시대', '저녁', '사장', '표', '지금', '보증', '증가', '내리다', '나다', '주다', '돌아오다', '하다', '위하다', '벌다', '생기다', '말리다', '내려오다', '있다', '밀다', '알다', '만들다', '대하다', '살리다', '이루어지다', '쏟다', '보내오다', '늘리다', '보다', '젊다', '어떻다', '비싸다', '이렇다', '같다', '안타깝다', '좋다']
    
    • 괜히 저 때문에 khaiii 설치하시고 일요일에 고생 많으셨습니다. 제가 문장 단위로 NLP를 한 이유는 단어 간 거리를 계산하여 단어의 유사도를 찾는데 목적이 있습니다. 가령, '저도 젊었을 때는 중소기업 사장을 했습니다' 에서 [젊다, 중소기업, 사장, 하다]를 추출하여 '젊다-중소기업'의 거리 1, 젊다-사장의 거리 2 등으로 재정리하여 단어 간 유사도를 측정하고자 합니다. 제가 파이썬 실력이 부족하여 매번 좌절하고 있습니다만, 선생님의 도움과 관심으로 또 다시 힘을 내고 있습니다. 다시 한 번 진심으로 감사드립니다. 알 수 없는 사용자 2020.2.2 22:54

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)