2015년 11월 28일 토요일

판다스 새로운 기능, 스타일(Style), 리뷰하기

2015년 11월 21일 배포된 0.17.1 버전의 새롭게 추가된 기능인 스타일(Style)의 기능을 알아본다.
스타일은 테이블과 플롯의 장점을 잘 버무려 준다.

본문은 스타일에 대한 직관적인 사용 예제를 다룬다.

먼저 샘플 데이터 셋을 만들었다.

from sklearn import datasets
import pandas as pd
iris = datasets.load_iris()
df = pd.DataFrame(iris.data,columns=iris.feature_names).head(6)
df.columns = ['SepalL','SepalW','PetalL','PetalW']
* 단순히 기능 테스트를 위한 데이터를 추렸다.
SepalLSepalWPetalLPetalW
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
55.43.91.70.4


다양한 스타일을 적용하는 예제이다.

수치의 크기를 색상 온도로 보는 것

df.style.background_gradient(cmap='magma', low=1)
* cmap은 colormap의 약자이고, 색상을 정의한다.
SepalLSepalWPetalLPetalW
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
55.43.91.70.4

수치를 막대기둥 형태로 보는 것

df.style.bar(subset=['SepalL','PetalL'], color='#d65f5f')
* subset을 통해서 대상 속성들을 선택한다.
SepalLSepalWPetalLPetalW
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
55.43.91.70.4

요소(elements) 단위로 분류하는 것

df.style.applymap(lambda i: 'background-color: red' if i > 3 else '')
* 테이블의 전체 요소마다 함수가 적용된다.
SepalLSepalWPetalLPetalW
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
55.43.91.70.4

컬럼(columns)이나 로우(row) 단위로 분류하는 것

yes = 'background-color: green'
no = 'background-color: orange'
df.style.apply(lambda L: [ yes if i*10 % 2 == 0 else no for i in L ], axis=0)
* 축(axis)에 따라 List 단위로 입력되는 것에 유의하자.
SepalLSepalWPetalLPetalW
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
55.43.91.70.4



상세한 내용은 원문을 참고하자.
http://pandas.pydata.org/pandas-docs/version/0.17.1/whatsnew.html

2015년 11월 27일 금요일

파이썬 함수 주석 요약

파이썬 함수 주석에 대해서 다룬다.

변수 타입을 명시하지 않는 이유로 자유롭지만 혼란스러운 부분을 주석을 통해서 가이드 할 수 있다.
주석은 제약사항은 아니지만 3rd party 라이브러리에서 의미를 해석할 때 매우 유용하게 사용된다.

  • PEP 3107에서 함수에 주석을 추가하는 구문을 소개한다.
  • PEP 484에서는 PEP 3107의 데이터 타입에 대한 의미적인 부분을 소개한다.

본문은 핵심 요약을 통해서 함수 주석 사용에 도움이 되는 것을 목표로 한다.

PEP 3107 - Function Annotations

입력값 (Parameters) 리턴값(return values)을 옵션으로 명시 할 수 있다.
Syntax:
def f(*args: <expression>, **kwargs: <expression>) -> <expression>:
<statements>
* 명시된 표현(<expression>)은 데이터 타입에 대한 주석이다.

컴파일 시, 주석된 표현은 계산된 결과로 재 표현된다.
def f(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
pass
help(f)
Output:
Help on function f in module __main__:
f(a:'x', b:11, c:list) -> 9

PEP 484 - Type Hints


명시된 표현(<expression>)이 없는 것(None)은 type(None)과 같은 의미다.

타입은 별칭 사용이 가능하다.

typing 라이브러리를 통해서 다양한 타입을 정의 할 수 있다.
( Any, Union, Tuple, Callable, TypeVar, and Generic )

복합 예제는 다음과 같다.
from typing import TypeVar, Generic
T = TypeVar('T',int,float)    # 'T'는 int or float type을 사용

def foo(x: T, y: T) -> T:

    return x + y
help(foo)
Output:
Help on function foo in module __main__:
foo(x:typing.T, y:typing.T) -> typing.S

class zoo(Generic[T]):    # Generic을 통해서 클래스에 포괄 적용
    def foo(x: T, y: T) -> T:
        return x + y
help(zoo)
Output:
Help on class zoo in module __main__:
class zoo(typing.Generic)
 |  Method resolution order:
 |      zoo
 |      typing.Generic
 |      builtins.object
 |  
 |  Methods defined hero:
 |  
 |  foo(x:typing.T, y:typing.T) -> typing.T


메모를 하듯이 주석을 하자.
주석할 수 없는 로직은 잔잔한 물결 앞에 모래성과 같다.

2015년 11월 26일 목요일

접속 지역 날씨 정보 추출 방법

사이트에 접속하는 사용자의 날씨 정보를 추출하는 방법을 다룬다.

정보 추출은 다음 두가지 절차가 있다.

1. IP 주소(Address)나 브라우저(Browser)로 부터 위치정보 가져오기
2. 위치정보로 날씨 정보 가져 오기


* 위치정보 : 지역이름이나 GPS 좌표 사용


몇 가지 주요 사이트를 대상으로 테이블로 정리한다. (2015년 11월 25일 기준)

분류 구분 특징 비용 비고
IP 위치코드 변환 MaxMind (GeoIP) 인지도 및 완성도 높음
API 문서 수준이 높음
로컬 DB 서비스(성능)
50,000 조회 20달러
DB 다운로드 초기 370달러
(업데이트 100달러/달)
KR 정확도 66%
IP-API REST API 제공 무료 : 분당 250
무제한 : 3달 45유로
KR 정확도 높음 (경험)
W3C 브라우저 레벨의 위치정보 사용 여부 확인
응답 데이터가 GPS 정보(Only)
무료 W3C 협회 표준
위치코드 날씨 변환 Yahoo 손쉬운 사용
단지 비 상업적으로 사용 가능
무료
 - 일당 : 2,000

OpenWeatherMap GPS 좌표 및 지역명 처리
손쉬운 사용
무료
 - 분당 : 60
 - 일당 : 50,000

공공 데이터 일일 트래픽 : 3000 제한
실황 조회 : 1000 제한
활용사례 등록 시, 100,000 까지 확대 가능
무료 위경도 좌표를 격자형(X,Y)로 변형 해서 사용

* MaxMind는 Trial Key를 발급 받아서 테스트 가능하다. 한국 주소에 대한 정확도가 무척 떨어진다.


공공 데이터(동네예보정보조회서비스) 가이드가 좀 ?해서, 절차를 요약한다.

1. 지역정보는 위경도 정보로 변경한다.
2. 위경도를 X,Y 형식의 좌표로 변환하는 C 소스를 컴파일 해서 사용한다.
3. API에 입력되는 위치값 (nx, ny)는 X,Y 형식의 좌표값을 입력한다. (Not 위경도)

* 위도 (Latitude), 경도 (Longitude)



각 사이트 API에 대한 샘플 코드 및 Json 형식의 결과는 다음과 같다.

 - https://bitbucket.org/snippets/juhoon26/AAR4r


2015년 11월 23일 월요일

파이썬 코드 품질 향상을 위한 PEP8 도구(Tools)

기존 블로그를 통해서 PEP8 가이드를 둘러봤다.
이번에는 PEP8을 가이드 하는 도구에 대해서 소개한다.

pep8와 autopep8

  • pep8
    • https://pypi.python.org/pypi/pep8
    • 코드 리뷰를 통해서 작성자에게 적절한 pep8 규칙을 가이드 한다.
  • autopep8
    • https://pypi.python.org/pypi/autopep8/
    • pep8을 기반으로 자동으로 코드를 수정한다.

* 각 도구는 상세한 옵션들을 제공한다.
* 본문에서는 간단한 사용 예제만 다룬다.

pep8 사용 예제

Mark$ pep8 --show-source sample.py
b.py:8:1: E302 expected 2 blank lines, found 1
def get_label_value(dict_):
^
b.py:21:1: E302 expected 2 blank lines, found 1
def is_label(dict_):
^
b.py:44:46: E231 missing whitespace after ','
        for next_obj in obj.find_all(RULE_ALL,recursive=False):
                                             ^
b.py:49:45: E231 missing whitespace after ','
                GLOBAL_LIST.append((next_lev,get_label_value(next_obj.attrs)))
                                            ^
b.py:58:1: E302 expected 2 blank lines, found 1
def main(file_name):
^
b.py:67:27: E231 missing whitespace after ','
    finder(file_name + '_',root)
                          ^
b.py:72:5: E265 block comment should start with '# '
    #RULE_DATA_FORMAT = re.compile('xsd:choice|xsd:restriction|xsd:sequence')
    ^
b.py:85:50: E231 missing whitespace after ','
    df = pd.DataFrame(GLOBAL_LIST,columns=['dist','name'])
                                                 ^
b.py:87:80: E501 line too long (82 > 79 characters)
    df['level'] = df['dist'].apply(lambda i: len(i.split('_')[-1].split('.')) - 1)
                                                                               ^
b.py:88:5: E301 expected 1 blank line, found 0
    def set_tag(name):
    ^
b.py:89:32: E701 multiple statements on one line (colon)
        if name.startswith('~'): return 'ref'
                               ^
b.py:94:40: E231 missing whitespace after ','
    df = df[['file','dist','name','tag','level']]

autopep8 사용 예제

Mark$ autopep8 --in-place --aggressive --aggressive sample.py

* --in-place 옵션을 통해서 sample.py 본문의 pep8 권고사항들이 바로 적용된다.
* 확인 차원에서 autopep8 사용 이후에 pep8을 돌려 보자.

2015년 11월 18일 수요일

파이썬의 코드 품질 향상을 위한 PEP 발취

파이썬의 한층 강화된 코딩을 위한 제안 PEP(Python Enhancement Proposals) 페이지이다.
 - https://www.python.org/dev/peps/

코드 품질 향상을 위해 다음 가이드를 다룬다.
 - 8 : Style Guide for Python Code

코드 스타일 가이드의 목적은 전사 차원의 가이드 제공을 통해서 프로젝트 마다 작성될 그들만의 가이드에 일관성을 부여 할 수 있다.

다음은 원문에 대한 요약 테이블이다.

분류 구분 원문 발취 요약
Code Lay-out Indentation Use 4 spaces per indentation level. 들여쓰기 1개당 4개의 공간을 사용하자.
Tabs or Spaces


Maximum Line Length Limit all lines to a maximum of 79 characters (and docstrings/comments to 72).
to using a backslash for line continuation.
79개의 문자 길이 제한하자.
코멘트의 경우 72개로 제한하자.
Blank Lines Surround top-level function and class definitions with two blank lines.
Method definitions inside a class are surrounded by a single blank line.
Use blank lines in functions, sparingly, to indicate logical sections.
최상의 함수나 클래스 : 2 줄
클래스 내부 매소드 :  1 줄
함수 내부 로직 섹션 : 1 줄
Source File Encoding Code in the core Python distribution should always use UTF-8 (or ASCII in Python 2).
Files using ASCII (in Python 2) or UTF-8 (in Python 3) should not have an encoding declaration.
All identifiers in the Python standard library MUST use ASCII-only identifiers
기본 인코딩
 - Python3 : UTF-8
 - Python2:  ASCII
식별자들은 ASCII를 사용해야만 한다.
Imports Imports should usually be on separate lines.
Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.
Wildcard imports ( from <module> import * ) should be avoided
라이브러리 단위로 구분 선언하자.
임포트는 파일의 상단에 선언하자.
 - 문서 요약(docstring)
 - 임포트
 - 전역 변수 선언
임포트 순서 (1 줄 띄우기)
 - 표준 라이브러리
 - 관계(3rd) 라이브러리
 - 로컬 명세 라이브리리
와일드카드(*) 사용을 피한다.
String Quotes use the other one to avoid backslashes in the string.
For triple-quoted strings, always use double quote characters 
싱글(‘), 더블(“) 병행 사용은 ‘\’ 사용을 피할 수 있다.
문서 요약을 위한 트리플(“””)은 더블(“) 만 사용하자.
Whitespace in  Expressions and Statements Pet Peeve Immediately inside parentheses, brackets or braces.
Immediately before a comma, semicolon, or colon:
Immediately before the open parenthesis that starts the argument list of a function call:
Immediately before the open parenthesis that starts an indexing or slicing:
More than one space around an assignment (or other) operator to align it with another.
공백을 사용하지 않는 유형
 - 괄호 바로 안쪽
 - 콤마/세미콜론/콜론 전
 - 리스트,함수 괄호 시작 전
 - 인덱싱,슬라이싱 시작 전
Other Recommendations Compound statements (multiple statements on the same line) are generally discouraged.
put an if/for/while with a small body on the same line, never do this for multi-clause statements.
문장/구문은 대략 한 라인에 표현하지 말자.
Comments Block Comments Block comments generally apply to some (or all) code that follows them, and are indented to the same level as that code. 코드와 같은 레벨에 처음에 ‘#’ 주석한다.
Inline Comments An inline comment is a comment on the same line as a statement. 간랸한 내용은 같은 라인에 ‘#' 주석한다.
Documentation String Write docstrings for all public modules, functions, classes, and methods. Docstrings are not necessary for non-public methods, but you should have a comment that describes what the method does. This comment should appear after the def line.
the """ that ends a multiline docstring should be on a line by itself.
모듈, 함수, 클래스, 매소드의 바로 뒤에 트리플(“””) 블럭을 사용해서 문서화 하자.
마침 트리플(“””)은 같은 레벨에 쓰자.
—— 예제 ——
“”” 제목
본문
“””
Version Bookkeeping



Naming Conventions Overriding Principle Names that are visible to the user as public parts of the API should follow conventions that reflect usage rather than implementation. 관습적인(익숙한) 이름을 사용하자.
Descriptive: Naming Styles Capitalized_Words_With_Underscores (ugly!)
_single_leading_underscore : weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.
single_trailing_underscore_ : used by convention to avoid conflicts with Python keyword,
__double_leading_underscore : when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo ; see below).
double_lading_and_trailing_underscore : Never invent such names; only use them as documented.
대문자화 문자는 Http에서 문제가 될 수 있자.
대문자화 문자와 밑줄을 섞는 건 최악이다.
_single_leading_underscore
 : 내부적인 이름으로 사용하자.
single_traing_underscore_
 : 예약어와 겹칠 때, 사용하자.
__double_leading_underscore
 : 클래스 속성 일때 _클래스__이름 형태로 변환됨
__double_leading_and_trailing_underscore__
 : 문서 가이드에 따라 사용하자.
Prescriptive: Naming Conventions Names to Avoid
Never use the characters 'l' (lowercase letter el), 'O' (uppercase letter oh), or 'I' (uppercase letter eye) as single character variable names.
l, O, I를 단문자 변수 이름으로 사용하지 말자.
Package and Module Names
Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.
모듈이름은 밑줄을 사용할 수 있고, 짧은 소문자를 사용하자.
패키지 이름은 짧은 소문자를 사용하자.
Class names
Class names should normally use the CapWords convention.
클래스 이름은 CapWords를 사용하자.
Exception Names
Because exceptions should be classes, the class naming convention applies here. However, you should use the suffix "Error" on your exception names (if the exception actually is an error).
예외 이름은 클래스 이름 형식에 접미사를 붙이자.
Global Variable Names
The conventions are about the same as those for functions.
전역 변수는 대략 함수와 같다.
Function Names
Function names should be lowercase, with words separated by underscores as necessary to improve readability.
함수 이름은 밑줄로 구분된 소문자를 사용하자.
Function and method arguments
it is generally better to append a single trailing underscore rather than use an abbreviation or spelling corruption.
함수의 입력변수 이름이 겹치면 후미에 밑줄을 붙이자.
Method Names and Instance Variables
Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.

Use one leading underscore only for non-public methods and instance variables.
To avoid name clashes with subclasses, use two leading underscores to invoke Python's name mangling rules.
메소드나 변수는 밑줄로 구분된 소문자를 사용하자.
비공개 메소드나 변수는 앞에 밑줄을 사용하자.
서브클래스는 앞에 두개의 밑줄을 사용하자.
Constants
Constants are usually defined on a module level and written in all capital letters with underscores separating words.
상수는 밑줄로 구분된 대문자를 사용하자.
Programming Recommendations