pandasでcsvファイルを読み込む際にあえてカラム(列)を分けない
ファイルの読み込みはいくつか方法があることは前回の記事に書いた。
読み込んだ後の処理を考えると、numpyやpandasで読みたい。でも中身が文字列を含む場合、numpyは使えないのでpandasで読むことになる。
困るのは読み込む対象のファイルの形式が整っていない場合。列数が揃っていない、特に先頭行の列数が少ない場合に読み込みエラーが起こる。
そんな場合は、あえて列を分けずにn行1列のデータフレームとして読み込む方法もある。以下のように引数の delimiter で改行コード'¥n'を指定すればOK。
列の分割はデータを読み込んだ後に必要な箇所だけ行う。DataFrameからリストやnumpy.ndarrayへの変換はいくつかの方法がある。それはまた別の機会に。
csvファイルやexcelファイル(xls, xlsx)を読み込む
csvファイルやexcelファイル(xls, xlsx)を読み込む場合のコードはいくつかあるのでまとめておく。
(1) 標準ライブラリのcsvを使う
第二引数を'rb'とすればバイナリファイルが扱える。
追加のライブラリが不要。.txt / .csvのどちらも読み込み可能。
空白や文字列があってもOK。
ただし、中身を取り出すのにfor構文が必要で不便。
(2) numpy を使う
np.ndarray型で読み込む。.txt / .csvのどちらも読み込み可能。
ただし,空白や文字列があるとエラーになる。
大抵は先頭行が項目名になってい流けど、その場合は引数をskiprows=1として1行スキップすればOK。
またはgenfromtxt()を使う。空白や文字列があるとnanにしてくれる。
(3) pandasを使う
pandas.Dataframe型で読み込む。.txt / .csvのどちらも読み込み可能。
空白や文字列があってもOK。
引数がたくさんあって色々調整できる。
header : 項目名に使う行を指定。Noneとしておくと項目名がなくなり、先頭行からデータとして読み込む
index_col:行名として使う列を指定。
その他の引数は省略。 下は関連記事へのリンク。
excelファイル(xls, xlsx)を読み込みたい場合は、read_excel()を使う。
詳しくは別記事で。
配列内の各要素に含まれる特定の文字列を置換・削除する方法
文字列の置換はreplace()を使う。
出力: 'Abcde'
これが使えるのは単独の文字列だけで、配列(各要素が文字列になっている配列)には使えない。
これを処理しようとするとエラーになる。
AttributeError: 'list' object has no attribute 'replace'
なので以下のように、配列を一旦単独の文字列に変換し、replace()で置換、のちに配列に戻すという処理をする。
出力: ['Abcde', 'Abcde']
ちなみに、このreplace()の2番目の引数を空白('')にしておけば、削除の処理ができる。
配列から要素をランダムに抽出するための「インデックス」を作る
配列から要素をランダムに抽出するには、(要素の抽出に使う)インデックスをランダムにしておくだけでいい。
random_array = array[random_index]
ここではrandom_indexも配列。
以下は関連記事。
順序をランダムにしたインデックス(配列)の作り方は色々ある。比較のため処理時間を測定。いずれも0~99,999の数字を重複なしでランダムに並べた配列を生成している。
→ 所要時間:17 msec
→ 所要時間:2.6 msec
→ 所要時間:2.0 msec
→ 所要時間:2.0 msec
np.random.randint() とnp.random.choice() が一位タイ。中身の処理は一緒なんだろうか。こうしてみるとnp.random.shuffle()も大して変わらない。
かと言って抽出するもとの配列そのものをランダムにシャッフルしようとすると、その配列のサイズが大きい場合は処理が重くなるのでやらない方がいい。
要素が全てnanの配列を生成をする
最近書くpythonコードの半分以上はnumpy.ndarrayを使ってる。
numpyがなかったら仕事にならない。それくらいお世話になってる。ただ一つだけ不満というか疑問に思っているのが要素が全てnanの配列を生成をする関数がないこと。要素が全て0の配列を生成する関数 numpy.zeros() があるならnumpy.nans() があってもいいと思うけど、なぜかない。何か理由があるんだろうか。
まあとにかく、そういう関数はないので自前で作るわけで、いつも下のようなやり方をしてる。
zeros()を使って狙いのサイズの配列を作成したのちに、全要素をnanにする、という処理を行う。(本当はempty()を使った方が計算コストが低いらしいけど)
作りたい配列と同じサイズの配列があったりする場合は、zeros_like() も便利。同じサイズで要素が全て0の配列を作ってくれる。
でもやっぱりnumpy.nans()が欲しい。
nan を含む配列の要素をシフトする
配列の要素をシフトさせる関数 shift() のことを前回書いたけど、この関数は配列内の要素にnanが含まれると使えない(出力する配列の要素が全てnanになる)という欠点がある。そして残念ながら今書いてるスクリプトでは配列にnanが入るので、結局自分でコードを書いた。
前回記事はこちら。
まずは1次元配列をシフトさせるコード。
それから2次元配列をシフトさせるコード。
もっと簡単にできるよ、という方いたらぜひ教えてください。行数減らしたいです。