음성학/음운론 연구를 위한 Python 맛보기
음운론학회 연구방법론 워크숍
2018년 12월 8일 (토)

음성학/음운론 연구를 위한 Python 맛보기 Part 2

Frequency 추출과 Entropy 계산

  • Part 1
    • Python 프로그래밍을 위한 variables 및 data type의 이해
    • control structure 소개
    • function과 class 소개
  • [x] Part 2
    • 문자열
    • file input 및 file ouput
    • packages (예, NLTK) 사용 소개
  • Part 3
    • Regular Expression
    • Unicode와 text encoding
    • Error 발생시 대처법

1. 문자열

Pig Latin

  • Pig latin은 단어를 바꾸는 게임이다. 단어를 바꾸는 규칙은 첫 모음 전까지의 자음을 떼어서 단어의 맨 뒤에 붙인다. 그리고 그 뒤에 ay를 붙여 준다. 예를 들어, “happy”라는 단어를 바꾸면 “appyhay”가 된다.

  • 이 pig latin을 코드로 작성하려면 몇 번째 문자가 처음으로 모음인지를 알아야 한다. 이와 관련해서는 후반부에서 다루기로 하고, 여기서는 문제를 단순화하여, 무조건 첫 문자 하나를 맨 뒤로 보내고 그 뒤에 ‘ay’를 붙이는 규칙으로 단어를 바꾸는 프로그램을 작성해 보자.

In [ ]:
from IPython.display import YouTubeVideo
# a short video about using Iphython
YouTubeVideo('3bzhtoeWcf0')

Maxwell the GEIO Pig TV Commercials

  • Maxwell: And if I tap my Geico app here, I can pay my bill. Tap it here, digital insurance ID card. And tap it here, boom, roadside assistance
  • Man: Ont'day ooklay, it's Axwellmay.
  • Woman: The igpay?
  • Man: Otallytay.
  • Woman: Take a icturepay!
  • Man: Onephay, onephay
  • Maxwell: Really, Pig Latin?
  • VOICE: GEICO, Anywhere, anytime. Just an aptay away on the GEICO appay.
In [ ]:
a = "Don't"
b = "Look"
c = "Maxwell"
new_a = a[1:] + a[0] + 'ay'
new_b = b[1:] + b[0] + 'ay'
new_c = c[1:] + c[0] + 'ay'
print(a, '->', new_a)
print(b, '->', new_b)
print(c, '->', new_c)

문자열의 첫 문자만 대문자로 변환하고, 나머지 문자들은 모두 소문자로 변환하고 싶다면?

  • capitalize()
In [ ]:
print("Applying pig latin and capitalizing the first letter:")
print(a, '->', new_a.capitalize())
print(b, '->', new_b.capitalize())
print(c, '->', new_c.capitalize())

control structure

  • if 조건문
  • for 반복문
  • while 반복문
In [ ]:
#define vowels
vowels = 'aeiou'
# set the word 
# Winnipesaukee (/ˌwɪnɪpəˈsɔːki/) is the largest lake in the U.S. state of New Hampshire)
word = 'Winnepesaukee'
# create two counters
counter = 0           # 글자 수 전체를 세기 위해서
vowelcount = 0     # 모음 철자를 세기 위해서
# while 문을 통해서 글자 하나 하나를 반복해서 살펴본다
while counter < len(word):
    # is current letter in a vowel?
    if word[counter] in vowels:
        vowelcount += 1
    # keep track of total number of letters
    counter += 1
    # When counter is too big, do this:
print('There are', vowelcount, 'vowels in this word')
In [ ]:
word = 'Winnepesaukee'
len(word)

딕셔너리(dictionary) 유형

  • dictionary 유형은 특정한 의미의 key 와 그에 대응하는 value로 연결되어 있는 컨테이너형 자료형
  • 리스트형보다 관리하기가 쉬워 많이 사용하는 자료형임.

  • 문법

    dictionary_name = {'key1' : 'value1', 'key2': 'value2', ...}

길이에 따른 단어들의 분류

words라는 이름을 가진 list에는 여러 개의 단어가 저장되어 있다. 길이가 같은 단어들끼리 사전으로 묶고 출력하는 프로그램을 작성해 보자. 이때, 단어의 길이가 ‘key’가 되고, 같은 길이를 가지는 단어들은 list로 묶어서 사전의 값으로 구성한다.

word = {‘book’, ‘pencil’, ‘mirror’, ‘to’, ‘for’, ‘with’, ‘cup’, ‘computer’, ‘chair’, ‘of’, ‘a’, ‘an’, ‘I’, ‘desk’, ‘school’, ‘cat’, ‘lamp’}
출력 예:
[4] words of length 4 -> [‘book’, ‘with’, ‘desk’, ‘lamp’]
[3] words of length 6 -> [‘pencil’, ‘mirror’, ‘school’]
In [ ]:
words = ['book', 'pencil', 'mirror', 'to', 'for', 'with', \
         'cup', 'computer', 'chair', 'of', 'a', 'an', 'I', 'desk', \
         'school', 'cat', 'lamp']

word_length = {} # empty dicitonary

for w in words:
    length = len(w)
    if length not in word_length:
        word_length[length] = []
    word_length[length].append(w)

print(word_length)
In [ ]:
for k, v in word_length.items():
    print(k, '\t', v)
#    print('[{}] words of length {} -> {}'.format(len(v), k, v))

Anagram

  • anagram은 같은 문자들로 구성된 문자열들을 말한다.
  • 예를 들어, 문자열 python의 anagram은 pythno, thnopy, ythopn 등이 있다. 즉, p, y, t, h, o, n으로 구성된 문자들이다.
  • dict을 이용하여 두 개의 문자열을 받아서, 두 문자열이 anagram인지를 판단하는 프로그램을 작성해 보자.
In [ ]:
word1 = input('Word1:')
word2 = input('Word2:')
D1 = {}
for w in word1:
    if w in D1: D1[w] += 1
    else: D1[w] = 1

    D2 = {}
for w in word2:
    if w in D2: D2[w] += 1
    else: D2[w] = 1
        
if D1 == D2:
    print('{} and {} are anagram'.format(word1, word2))
else:
    print('{} and {} are not anagram'.format(word1, word2))

Palindrome인지 확인하는 문제

  • 앞에서부터 읽으나 뒤에서부터 읽으나 같은 문자열을 ‘Palindrome’이라고 한다. 하나의 문자열을 입력받아서 Palindrome인지 판단하는 프로그램을 작성해 보자.

  • The word palindrome was coined from the Greek roots palin (again) and dromos (way, direction) by the English writer Ben Jonson in the 17th century.

link to a webpage for palindrome list

In [ ]:
string = input('string (ex, tattarrattat): ')
if string == string[::-1]:
    print(string, 'is a palindrome.')
else: print(string, 'is not a palindrome')
In [ ]:
string = input('string (ex, tattarrattat): ')
reverse = ''.join(list(reversed(string)))    # another way of checking palindrome
if string == reverse:
    print(string, 'is a palindrome.')
In [ ]:
a = 'pat'
list(reversed(a))

문자열에서 자모음의 개수 counting하기

  • 문자열을 입력받아 자음의 개수와 모음의 개수를 구하는 프로그램을 for 반복문을 이용하여 작성해 보자.
In [ ]:
string = input('Enter string: ')
vowel_count = 0
consonant_count = 0
for s in string:
    if s.lower() in 'aeiou':
        vowel_count += 1
    else:
        consonant_count += 1
print('number of vowels: {}'.format(vowel_count))
print('number of vowels ', vowel_count)      
print('number of consonants: {}'.format(consonant_count))

리스트에서 단어 색인 찾기

  • list에는 여러 개의 영어 단어가 저장되어 있다. 하나의 단어를 입력받아서 리스트에 그 단어가 대소문자 구별 없이 몇 번 index에 저장되어 있는지와 저장된 글자대로 출력하는 프로그램을 작성해 보자.
L=[‘apple’, ‘APPle’,  ‘Melon’, ‘melon’, ‘Grape’, ‘kiwi’, ‘appLE’, ‘KIwi’]

예상 결과:
Enter word to find: apple
0 – apple
1 – Apple
6 - appLE
In [ ]:
L=['apple', 'APPle',  'Melon', 'melon', 'Grape', 'kiwi', 'appLE', 'KIwi']

word = input('Enter the word to find:')
for i in range(len(L)):
    if L[i].lower() == word:
        print('{}{}'.format(i, L[i]))

Python을 이용한 언어 분석의 예

flowchart

In [ ]:
# string 정의하기
sentence1 = "Monty python is full of memorable quotes"
sentence2 = "My hovercraft is full of eels."
sentence3 = "You're all individuals"

# lists
mini_text = [sentence1, sentence2, sentence3]

# number of sentences
number_of_sentences = 3

# loops
for current_sentence in mini_text:
    #print(current_sentence, type(current_sentence))
    number_of_characters = 0
    for character in current_sentence:
        number_of_characters =  number_of_characters + 1
        
    number_of_words = 0
    for word in current_sentence.split():
        #print(word, type(word))
        number_of_words += 1
        
    average_word_length = float(number_of_characters)/number_of_words
    
    print(current_sentence)
    print("number of words: ", number_of_words)
    print("number of characters: ", number_of_characters)
    print("This sentence has about %f characters per word" % (average_word_length))

Pig Latin (revisited, but not completed)

In [ ]:
# an affix used in Pig Latin
ay = "ay"
original = input("Enter a word: ")
if len(original) > 0 and original.isalpha():
    word = original.lower()
    first_letter = word[0]
    if first_letter in 'aeiou':
        new_word = word.capitalize() + ay
        print(new_word)
    else:
        new_word = word[1:].capitalize() + first_letter + ay
        print(new_word)
else:
    print("empty string")

2. File input and file output

  • 표준입출력
    • 키보도로 입력하고, 모니터로 출력하는 것
  • 파일입출력
    • 파일(file)로부터 데이터를 입력받아 처리한 후, 결과를 파일에 저장하는 것
In [ ]:
! ls data/* # in window: ! dir data/*
In [ ]:
f = open('data/testfile.txt', 'r')
contents = f.readlines()
print(contents)
f.close()

print() 함수로 파일에 데이터 저장하기

In [ ]:
with open('newfile.txt', 'w') as f:
    print('hello world', file = f)
    print('python programming', file=f)
In [ ]:
fin = open('newfile.txt', 'r')
contents = fin.readlines()
print(contents)
fin.close()

for line in contents:
    print(line.strip())
In [ ]:
#define vowels
vowels = 'aeiou'
#get the word from the user
word = input("Type a word: ")
#proceed as before...
counter = 0
vowelcount = 0
while counter < len(word):
    if word[counter] in vowels:
        vowelcount += 1
    counter += 1
else:
    print('There are',vowelcount, 'vowels in this word')

3. nltk (natural language toolkit)과 같은 package 사용하기

nltk는 파이썬으로 작성된 자연언어처리도구이다. 품사태거를 포함해 많은 유용한 도구들이 있다.

import nltk를 타이핑했는 데, error가 나오면 아래와 같이 명령어를 타이핑하여 nltk를 설치함.

  • pip (pip installs packags)은 파이썬 모듈이나 패키지를 쉽게 설치할 수 있도록 도와주는 도구임.
  • !(은어로 bang이라고 불리기도 함)다음에 pip3 install nltk
In [ ]:
! pip3 install nltk
In [ ]:
import nltk
sentence = """At eight o'clock on Thursday morning"""
tokens = nltk.word_tokenize(sentence)
tokens
tagged = nltk.pos_tag(tokens)
tagged
In [ ]:
from nltk.corpus import treebank
t = treebank.parsed_sents('wsj_0001.mrg')[0]
t.draw()

4.4 Lexical Frequency in Alice in Wonderland

  • Lewis Carroll이 쓴 Alice's Advenctures in Wonderland를 사용하여 어휘 통계치를 산출하는 프로그램을 작성해 보자.

  • Project Gutenberg (http://gutenberg.org)에서 텍스트 파일을 구할 수도 있으며, 본 워크숍을 위해 준비한 data 디렉토리의 파일에도 alice.text라는 filename으로 찾을 수 있다.

In [ ]:
# open the file
fin = open('data/alice.txt', 'r')
text = fin.read()
fin.close()
#print(text)
In [ ]:
# convert to lowercase and split into words
words = text.lower().split()
print(words[:50])
In [ ]:
words_str = ' '.join(words)
import re

# substitution punctuation marks with blank 
# NOT COMPLETE
new_words = words_str.replace(',', '')

new_words_list = new_words.split()
print(new_words_list[:100])
In [ ]:
worddict = {}
for w in new_words_list:
    if w in worddict:
        worddict[w] += 1
    else: 
        worddict[w] = 1

for wrd, freq in sorted(worddict.items(), key=lambda t : t[1], reverse=True): 
    print(wrd, '\t', freq)

# lambda 함수에 t와 t[1]을 사용하였는데, 
# 여기에서 t는 worddict.items()에서 얻은 목록에 들어 있는 항목을 의미하며,
# t 항목은 ('key', value) 튜플로 되어 있습니다. 
# 그렇기 때문에 t[1]은 value를 의미하여 정렬하는 키를 value로 하라는 의미입니다

파일에 결과물을 저장하기

In [ ]:
# open output file
fout = open('data/alice_lexcal_freq_result.txt', 'w')
for wrd, freq in sorted(worddict.items(), key=lambda t : t[1], reverse=True): 
    fout.write(wrd+'\t'+str(freq)+'\n')
fout.close()
In [ ]:
! head -50 data/alice_lexcal_freq_result.txt
In [ ]: