にわかオタクによるにわか忘備録

にわかなオタクの試行錯誤を忘備録的にまとめているブログです.にわかなのでやってる事が全体的にお遊び感ある&所々誤りがあるのは否めませんが,生暖かい目で見ていただければと思います.

Numpy,Pandasを用いたデータ分析で何となくひっかかりそうな所

Pythonでデータ分析をやってはや数年になるが,ものぐさなためちょっと調べた事を忘れて何回も調べ直す非効率的な事を数え切れないくらいやらかしてきた様に思う.そこで,いい機会なのでよく出て来たテクニックやエラーの対処法をまとめたいと思う.なお私は情弱おじいちゃんなのでここでの話の対象はPython2.7に限定されるし,挙動云々のちゃんとした話を見たい人は読まない方がいい.

データの読み込み・書き出しについて

Numpyを使う場合以下の様に行う事が多い.

import numpy as np
# データの読み込み
data = np.loadtxt('hogehoge.csv',delimiter=',',dtype=np.string_) # csvファイルやtxtファイルを読み込むケース
data = np.loadtxt('hogehoge.tsv',delimiter='\t',dtype=np.string_) # tsvファイルを読み込むケース

#データの書き出し
np.savetxt('hogehoge.csv',data,delimiter=',',fmt='%s') # csvファイルやtxtファイルを書き出すケース
np.savetxt('hogehoge.tsv',data,delimiter='\t',fmt='%s') # csvファイルやtxtファイルを書き出すケース

読み込みに関して,特にクレンジング前のデータを読み込む時は決まってエラーが発生してしまう.そのため,とりあえずデータ型はnp.string_にしておいて,必要に応じて書き換えるなどするといい気がする.データによって区切り文字は異なるので,これもデータに応じた適切なdelimiterを指定して柔軟に対応しよう. 逆に書き出す場合は,基本的にはfmt='%s'としておけばいいのだが,データに指数表記を含む場合そのまま文字列として認識され,書き出したりExcelで参照する時などに非常に不都合である.このため,状況に応じfmt='%d'とかfmt='%f'を使う必要がある. Pandasを使う場合は次の様にする.

import pandas as pd
# ファイルを読み込むケース
data = pd.read_csv('hogehoge.csv',header=None,names=['hoge1','hoge2','hoge3']) # csvファイルを読み込む場合
data = pd.read_csv('hogehoge.tsv',delimiter='\t',header=None,names=['hoge1','hoge2','hoge3']) # tsvファイルを読み込む場合
# ファイルを書き出すケース
data.to_csv('hogehoge.csv')

pandasの場合,デフォルトでdelimiter=','とされているためcsvファイルを読み込む時は区切り文字の指定をしなくてもいいが,tsvファイルを読む時はdelimiter='\t'とする必要がある.この辺も状況に応じて使い分けよう. また,pandasでは先頭行をヘッダとして認識するため,データにヘッダがない場合ではheader=Noneとして指定しておく必要がある.この時,ヘッダは0,1,2,3,…と振られるが,データ型は整数になっているため,例えばdata['3']の様に列を指定するとエラーを吐いてしまうので注意.

リストの内包表記について

Pythonは簡単に書けるというメリットはあるものの基本的に律速なため,for文を何も考えず書くととんでもなく処理に時間がかかることがある.このため(特に何らかの理由でNumpy等を使えない場合)リストの内包表記を使える所に使うことは結構重要である.以下によく使いそうなパターンを書いておく.

hoge = [i for i in xrange(10)] # 最もシンプルなfor文
hoge = [[i,j] for i in xrange(10) for j in xrange(10)] #二重for文.for i in~:for j in ~:と書いてるのと同じ
hoge = [i for i in xrange(10) if i%2==0] #if文が入る場合.
hoge = [i if i%2==0 else 0 for i in xrange(10)] #if~else文が入る場合.if~elseの後にfor文を置く.
hoge = [1 if i%3==0 else 2 if i%3==1 else 3 for i in xrange(10)] #elifはelse (処理) ifに変換

文字コードのお話(適当)

整数や実数を扱うなら基本的には無縁だが,データ分析をやっているとテキストデータの処理をしないといけないケースは多々発生する.特にPythonでは文字コードの処理をキチンとしないとエラー塗れになる. 私自身,文字コード問題については余り理解が及んでいないのだが,文字コードを扱う場合の基本的な方針としては,

  • 文字コードは必ず揃える(if str(a)==b.decode('shift-jis')みたいなコードを書かない)

  • Python2.7ではasciiがデフォルトだが,パッケージによってはUnicodeが使われることもあるので極力Unicodeを使う

を守っていれば大体何とかなりはする.よく使うコードは次の通り.

(u'hogehoge').encode('utf-8') #hogehoge(Unicodeで表現された文字列)をasciiに変換する
'hogehoge'.decode('utf-8') # hogehoge(asciiで表現された文字列)をUnicodeに変換する

decode() の()の中身は'utf-8'でも'shift-jis'でもいい.この辺は状況に応じ使い分ける.