helloworlds

not a noun, it's a verb

【Python】PandasでExcelファイルを読み込んでtsvファイルにおこす

今回はタイトル通り、 Excelファイルから新たにtsvファイルを生成させるコマンドラインツールなるものを作成しました。

よく会社でG suiteでデータをスプレッドシートなんか管理されているかと思います。 だんだんデータが溜まっていくと、開くのに時間がかかったり、大事な情報だときちんとヴァージョン管理したいと思ったりしたことがあるかと思います。

また、スプレッドシートだと誰かが変更したりすると履歴が追いにくい... (※ 最近?また履歴確認機能がアップデートされましたが、「なんかな〜 ん〜 見にくいというかそもそも履歴とか見ない」とかとか..) ミスってコピペする場所間違えたのに気づかない... とかあるかと思います。

そこで、Githubで管理してみるか!となったのはいいものの、 GithubだとExcelファイルそのまま管理させても表示されないですよね。

なので、Githubでは、csv/tsvファイルに対してRenderingされる機能があるのです。 まあ既に知ってる方もいるかと思います。

さて、Excelファイルからcsv化しよう!となるわけです。

保存するときに拡張子を変更すれば問題ないです。 ただ、「どうせ管理するなら、このファイル○○毎に分けて管理しない?」ってなります笑

ならないならいいんです笑 ただ、スプレッドシートExcelファイルを読み込んで、新たにある規則に基いてcsv化しようってなって、 さらにデータ(セル)が多いと中々手作業だと時間が取られる作業になってしまいます。

なので、Pythonを使ってあるワードに対して、ワードにマッチした行をヘッダー付で抽出し、新たに(私の場合は)tsvファイルを生成しようというわけです。

Pythonコマンドラインツールみたくなるようにしました。

イメージとしては以下。

$ python3 create_tsv.py --file target.xlsx --word target_word

こんなかんじでローカルで実行すると、同階層にtsvファイルを生成され、 そのままGithubにあげるとこんなかんじで参照できるようにします。

f:id:o21o21:20180426161834p:plain

ちなみにこのRendering機能では、フィルタできる機能もデフォルトであるのでシンプルに使えて便利です。

さて、実行環境を確認していきます。

開発環境

言語: Python (version 3.5.0) Pythonのversionを簡単に切替できるツールは、過去記事にあるので、よかったら観覧してみて下さい。 OS: macOS 主なlibrary: pandas (version .22.0), xlrd

準備

Excelファイル

今回は元となるExcelファイルが必要です。

想定するExcelファイルはこんなかんじとします。

xx xx
No 列一 列二 列三 列四 列五 列六
1 aaaa bbbb cccc dddd eeee ffff
2 aaaa bbbb cccc dddd eeee ffff
3 zzzz bbbb cccc dddd eeee ffff
4 aaaa bbbb cccc dddd eeee ffff
5 zzzz bbbb cccc dddd eeee ffff
6 aaaa bbbb cccc dddd eeee ffff
7 aaaa bbbb cccc dddd eeee ffff

ちょっと分かりづらいですが、上2段がheader(ヘッダー)です。 xxも何かしらのheaderだと思って下さい。

このheaderが2つある(しかもheaderの上段と下段でheader数が相違している)ことで私はハマりました... それは後ほど説明します。

こうしたExcelファイルを置いておきます。

Pythonファイル

とりあえずsample.pyとしてPythonファイルを作成します。

ライブラリインストール

$ pip3 install pandas
$ pip3 install xlrd

pandas

今回pandasという、主にデータ解析を得意とするライブラリを使っていきたいと思います。 知ってたのですが、ちゃんと触る機会がなかったので、面白かったです!

xlrd

xlrdは、Excel(xls)のデータをPythonで読むためのライブラリです。 xlrd自体のExcelデータの抽出順序は、book → sheet → cell です。

準備はこれくらい。

本来、requirements.txtを作成しておけばいいですが、今回はそんなボリューム感あるコードでないので割愛します。

コード書いていく

さきほど作成したsample.pyを開いて、さっそくコード書いていきます。

1. ライブラリの定義とコマンドラインオプション

まずは、ライブラリのimportから。

# coding:utf-8

import pandas as pd
import sys
import argparse

pipでインストールしたライブラリを定義しておきます。

続いて、イメージ通り作成するとなると、コマンドラインからオプションを指定することで 後々使い勝手がよくなりますので、オプションを受け付けるようにします。

ここではargparseを使います。 コードがどんな引数を期待するのか定義するためです。 もし、想定外の引数がわたってきたらエラーを発生させます。

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--file", type=str)
    parser.add_argument("--word", type=str)
    arg = parser.parse_args()
    return(arg)

--file--wordをオプションで受け付けるようにしました。

argをreturnしているので、

option = get_args()

として、option.fileみたいにコード内で使えます。

2. Excelファイルを読み込んでシートを確認する

まずは、Excelファイルを読み込みます。

# get Excel file from Command line
excel_file = './' + option.file

# Open excel_file (xls,xlsx)
input_file = pd.ExcelFile(excel_file)

ここでpandas登場です。 pd.ExcelFile()で、ExcelfileオブジェクトとしてPythonから参照できます。

そして、シートを取得します。 もちろんExcelファイルによっては、シートが沢山あるものも存在しますよね。

# get Sheets
sheets_name = input_file.sheet_names

これでsheets_name[0]とかやってシート名を参照します。

3. DataFrameとして対象のシートの読込

ここでparseという関数を使用します。 こうすることで、対象のシートをDataFrameとして取得します。 パラメータはこれ以外にもあるので、公式を参照しましょう。

df_sample = input_file.parse(sheets_name[0],
                              skiprows=1,
                              header=[0,1],
                              index_col=0,
                              names=headers,
                              usecols="B:E,G:H" 
                              )

第一引数には、対象シートを指定します。

  • skiprows 対象シートの一番上の行から、いくつ読み飛ばすか指定します。 今回は1行飛ばすかんじです。

  • header skiprowsでスキップしたところから、headerが何行あるか(もしくはheaderの有無)を指定します。 今回は、headerが2行ある想定なので[0,1]を指定。

  • index_col indexとするcolumn名を指定します。 今回は、No.の列をindex扱いにしようかと思います。

  • names カラムの名前を指定します。 今回だとheadersという変数を指定しています。後ほど詳細を説明します。

  • usecols 特定の列を読み込む場合に指定します。 今回だとB:E,G:Hなので、ExcelファイルのB〜E列とG〜H列を抽出させます。

これでDataFrameとして色々なメソッドを使用してアクセスできるようになりました。

4. 指定したwordにあったデータを抽出する

コマンドラインからオプションで指定するword(例: --word zzzz)のみを抽出する必要があるので、 DataFrameにアクセスして対象を検索します。

今回は、列1のzzzzという文字列を検索すると想定します。

df_ordered = df_sample[df_sample.ix[:, 0] == option.word]

データにアクセスする方法として、今回はixを使用します。 開発中、locilocも使用したのですが、headerが2行あることでなのか?うまくいかずでした...

こちらが参考になりました。

行ラベルを指定せず、列ラベルを指定します。(intで)

5. 不要な列を除外

列4を除外する想定です。 dropメソッドを使用します。 columnsを指定することで簡単に除外できます。

df_dropped = df_ordered.drop(columns=[('', '列四')])

いざtsvファイルとして吐き出す

to_csvメソッドですが、tsvはタブ区切りなので問題ないです。 パラメータsepで指定します。

output_file = 'output_' + option.table + '.tsv'
df_dropped.to_csv(output_file,
                sep="\t",
                header=True,
                encoding="utf-8"
                )

ここまでできればもう出力されます。

が、1点記事上部で述べていたheaderが2行あること(header数がheader同士で相違)でおこる問題がありました。 私がまだpandas初心者なのでうまい方法があったかもしれませんが、詰まったのでメモです。

3. DataFrameとして対象のシートの読namesの指定を変数にしました。 結果から言うと、これが解決策でした。

どういうことかと言うと、 基のExcelファイルでheaderが2行あって、尚且つheader数が一致しないと headerがMultiIndexとして扱われていました。

そのせいでコマンドラインから指定するwordとの判定にも苦労しましたし、 不要な列の削除するdropメソッドのところも苦労しました。

drop(columns=[('', '列四')])となっていますが、この正体は以下になります。 (これがheaders変数)

headers = pd.MultiIndex.from_tuples([('', '列一'), ('', '列二), ('xx',列三'), ('xx',列四'), ('',列五')])

pandasのfrom_tuplesを使いました。 これで明示的にMultiIndexの階層化するわけです。 今回はparseメソッドのパラメータに直接ぶち込みました笑 本来であれば、DataFrameにする際のcolumnsパラメータでうまいこと指定するようです。

というわけで、headers変数は、ファイルの上部に定義しておきましょう!

さて、これで以上です。 あとは、コマンドラインからpythonコマンドを実行して、 生成されたtsvファイルをそのままgithubにあげましょう!

pandasを初めてちゃんと触りましたが、非常に面白かったです。 これからも少しずつ触ってもう少し慣れたらと思います。

【Go】helloworldで最も基本的な構文を抑える

Golangの"HelloWorld"で最も基本的な構文を覚えていきたいと思います。

今回参考にするのはこの技術書です!

スターティングGo言語 (CodeZine BOOKS)

スターティングGo言語 (CodeZine BOOKS)

versionですが、私は1.9.2使用します。

golangでは、プロジェクト毎にversion管理したい場合、gvmというものがあるので、 そちらで切り替えて挙動を検証することが可能です!

過去記事でgvmのインストールも紹介しているので宜しければ観覧してみて下さい!

o21o21.hatenablog.jp

さっそく基本構文に...と、いきたいところですが、 きまりのそもそも系を先にまとめます。

Go

Go言語は、Googleによって開発されたプログラミング言語である。 2009年に発表されたので、まだまだ新しい言語ですね~。

そして、コンパイル型の言語です。

仮想マシンを備えていなく、実行環境が不要です。 オーバーヘッドが少ないことも1つの特徴でしょう。

いろんなOSにおける最も標準的な共有ライブラリさえ依存しない実行ファイルを生成します。

よく並行処理なんて言葉を見聞きするかと思いますが、 Goの場合は、ゴルーチン(goroutine)という並行処理の枠組みになります。 OSが提供するスレッドよりも小さな単位で動作するGO独自の実行単位です。 チャンネルというデータ構造を組み合わせされるようにデザインされています。

色々特徴がありますが、ネイティブコードにコンパイルされた上で実行されるので 一般的なスクリプト言語より何十倍もパフォーマンスが高いって覚えておきましょう。笑

これくらいにしてHello Worldをします。

いきなりコード

実行環境やGOPATHに関数ことは、過去記事に記載してあるのでそちらを参照して下さい。

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello World!!!")
}

上記プログラムをhello.goというファイル名で保存。

当ファイルがあるディレクトリで、

$ go run hello.go

として、Hello World!!!と返ってきたら成功です。

go runコマンドは、ビルドプロセスをコンソール上に出力させずに直接プログラムを実行できます。

次にプログラムの中身について見ていきます。

package

package main

変数や関数などプログラムのすべての要素は、パッケージに属すということを覚えておきましょう。 また、1ファイルに複数のパッケージの宣言はエラーがかえってきます。 なので、上記のコードだと「このファイルはmainパッケージですよ」ということを宣言しています。

import

import (
    "fmt"
)

Goのライブラリは、すべて固有の名前を持つパッケージとして提供されています。 今回は「fmtパッケージをインポートします」といっていますね。

また、Goのポリシーで不要なパッケージ(プログラムで宣言されてはいるが、使用されていないパッケージ)があると、コンパイルエラーがかえってきます。

このコンパイルエラーの回避は以下の書き方で回避できます。(パッケージ名前にアンダーバー)

import (
    _ "fmt"
)

エントリーポイント

こちらはコードを書いたことがことがある人ならば問題なさそうなので飛ばします。

ビルド

$ go build -o helloworld hello.go

上記コマンドで実行ファイルが作成されます。 -oオプションは、実行ファイル名の指定ですので、私は付けることをおすすめします。

無事、実行ファイルができたらあとはそのファイルを実行するだけです!

$ ./helloworld
Hello World!!!

完了です!

この実行ファイルですが、ただHello World!!と返すだけなのに、 容量が多いことに気付きます。

これは、記事上部で説明にある通り、OSのライブラリに依存しないためです。 ランタイム本体と指定したパッケージの機能すべてが実行ファイルの中に格納されているというわけです。

以上

【Kali Linux】をインストール

以前Kali Linuxをインストールしていましたが、久々なのでまた再度インストールし直そうかと思いました。

なので、手順なんかをメモがてらメモっていきます。

f:id:o21o21:20180421222328p:plain

環境: macOS

virtualboxをインストール

以下のURLをからインストールします。

Oracle VM VirtualBox

仮想環境を作成するのには欠かせないですね。 既にインストール済の方はスキップしても構いません。

※ ヴァージョンが古い方はこの機会にヴァージョンアップしましょう!w

Oracle VM VirtualBox Extension Pack

こちらは、VirtualBoxの機能拡張プラグインです。 どうやらVirtualBox4.0以降、ライセンスの関係でデフォルトで導入していないとのこと。 Oracle VM VirtualBox Extension Packを以下からDLしておきましょう。 ※ こちらも導入済の方はスキップOK

Oracle VM VirtualBox - Downloads | Oracle Technology Network | Oracle

これをDLしておかないとImplementation of the USB 2.0 controller not found!こんなエラーが出るかと思います。

Extension Packは以下の機能が入っている。

  • USB 2.0 コントローラ (EHCI)← 今回はこれがいる!!
  • USB 3.0 コントローラ (xHCI)(バージョン5.0から追加)
  • Remote Desktop Protocol(RDP)による遠隔制御機能 (マイクロソフトおよびシトリクスにより開発された、プロプライエタリな遠隔制御プロトコル。つまりWindowsリモートデスクトップクライアントやrdesktopソフトウェアから接続することが可能)
  • IntelカードによるPXEブート機能
  • シームレスモード (ホストOSとゲストOSのデスクトップの操作を統合する機能) (Wikipedia引用)

Extension Pack導入手順

上部のVirtualBox→設定から、以下のプラスボタンでDLしたextpackを選択。

f:id:o21o21:20180421220040p:plain

インストール同意しますpwd入力 → 以下のように成功したら完了。

f:id:o21o21:20180421220348p:plain

イメージファイルを取得

Kali Linux Custom Image Downloads - Offensive Security

現在(4/21/2018)のversionは、2018.1でした。

Kali-Linux VBox 64-Bit [OVA]をクリックしてDL開始。 およそ3GBくらいあるので、少々時間がかかるかもしれません。

f:id:o21o21:20180421104430p:plain

DLしたらVirtualBoxを起動しましょう。

VirtualBoxでインポート

ファイルから仮想アプライアンスのインポートを選択し、 先ほどDLしたイメージを指定。

f:id:o21o21:20180421211709p:plain

仮想アプライアンスの設定で、すべてのネットワークカードのMACアドレスを再初期化 に チェックをいれてインポートを押下。

少し経つと既に環境ができあがります!

あとは、好みやしたいことに合わせて設定を変更しましょう。

例えば、Kali Linuxだと仮想環境同士、OS同士のテストなど行う想定などなど ご自分で調べて設定を変更します。

CPUだとこんなかんじで簡単に変更できますね!

f:id:o21o21:20180421214331p:plain

起動

さっそく起動させてみましょう。

今回の環境を選択しVirtualBox起動ボタンで起動。

新たにウィンドウが立ち上がるかと思います。

少し経つとこのような画面になりますね。

f:id:o21o21:20180421220916p:plain

username? となりますが初回ログインはrootで入ります。

Username: root pwd: toor

はい!

f:id:o21o21:20180421221254p:plain

これで完了です!

あとは、日本語化ややキーボードの設定、タイムゾーン、お好みのブラウザやアプリの設定だけです。 基本的には、apt-getコマンドが使用できるかと思います。

普段から親しんでいるエンジニアは日本には少ないので、 日本語の記事が少ないかと思います。

英語でもググってみると参考になる記事も見つかる確立が高いでしょう!(KaliLinuxに限ったことではないですが...)

今後、何かしらKali Linuxを使った記事も出せればと思います。 (※ Kali Linuxに標準で入っているアプリの中には十分な知識が必要とするものが多々ありますので、よく理解してから使用するようにしましょう。場合によっては、知らずして法律に反してしまうことも考えられます。)

以上

【Python】pyenvをインストール&おまけhomebrew

pyenv

pyenvとは、pythonの環境管理ツールの1つで、 バージョン管理が容易に行えます。

macにはdefaultでPythonが入っていますが、pyenvを導入することで プロジェクト単位でのヴァージョン管理などの手助けになりそうですね。

pyenvのインストール元はこちらです。

インストール

$ git clone git://github.com/yyuu/pyenv.git ~/.pyenv

$HOMEディレクトリに.pyenvが生成されます。

続いて.bash_profileに以下を記述します。

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

.bash_profileを反映するのを忘れずに!

確認します。

$ pyenv -v

pyenv 1.2.3-45-g63c4b7f

簡単にコマンドを確認

  • インストールできるヴァージョンの一覧を確認
$ pyenv install --list

Available versions:
  2.1.3
  2.2.3
  2.3.7
  2.4
  2.4.1
  2.4.2
略
  stackless-3.2.5
  stackless-3.3.5
  stackless-3.3.7
  stackless-3.4-dev
  stackless-3.4.1
  stackless-3.4.2
  stackless-3.4.7
  stackless-3.5.4
  • 任意のヴァージョンをインストール
$ pyenv install 3.6.2
  • インストールしたヴァージョンの確認
$ pyenv versions
  • バージョンを切り替える

global: 常時使用(グローバル)されるPythonのバージョンを設定する。

local: では、.python-versionというファイルが作成され、特定のディレクトリのみ任意のバージョンが使用できるようにする。

$ pyenv global 3.6.2
$ pyenv local 3.6.1
  • アンイストール
$ pyenv uninstall 3.6.1

おまけ

brew updateできない

今回のpyenvに限った話ではないのだが、pyenv installをするときになんかエラーが出た。

python-build: use openssl from homebrew
python-build: use readline from homebrew
Downloading Python-3.6.2.tar.xz...
-> https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz
Installing Python-3.6.2...
python-build: use readline from homebrew

BUILD FAILED (OS X 10.13.4 using python-build 1.2.3-45-g63c4b7f)

Inspect or clean up the working tree at /var/folders/qm/crn7sz_16_q237fcphtfrr240000gn/T/python-build.20180419212305.32328
Results logged to /var/folders/qm/crn7sz_16_q237fcphtfrr240000gn/T/python-build.20180419212305.32328.log

Last 10 log lines:
  File "/private/var/folders/qm/crn7sz_16_q237fcphtfrr240000gn/T/python-build.20180419212305.32328/Python-3.6.2/Lib/ensurepip/__main__.py", line 4, in <module>
    ensurepip._main()
  File "/private/var/folders/qm/crn7sz_16_q237fcphtfrr240000gn/T/python-build.20180419212305.32328/Python-3.6.2/Lib/ensurepip/__init__.py", line 189, in _main
    default_pip=args.default_pip,
  File "/private/var/folders/qm/crn7sz_16_q237fcphtfrr240000gn/T/python-build.20180419212305.32328/Python-3.6.2/Lib/ensurepip/__init__.py", line 102, in bootstrap
    _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/private/var/folders/qm/crn7sz_16_q237fcphtfrr240000gn/T/python-build.20180419212305.32328/Python-3.6.2/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1

調査をしてみると、HighSierraを搭載したから出てきたエラーみたい。 たしかに最近上記を実行したPCのOSをバージョンアップした...

なるほどなるほど、と色々試してみたが解決できなかった...

が、原因が当初よくわからなかったのでググり方をミスっていた。 要は、再度homebrewをインストールすれば解決するとのこと。

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

brew updateもできたし、pyenv installも解決した。

よかったーーー

以上.

【Go】gvm installができん...

ちょっといつもと違うPCでGoの環境を整えていたんだけど、 何故か gvm install ができない....

ERROR: Failed to compile. Check the logs at /Users/username/.gvm/logs/go-go1.9.2-compile.log
ERROR: Failed to use installed version

あれーと思って調査していたところ、こちらのログを確認。

failed MSpanList_Insert xxxxxxxxxxxxxxxxxxxxx
fatal error: MSpanList_Insert

そこでググった。

gvmのgithubにも確かに記載されている。

https://github.com/moovweb/gvm#a-note-on-compiling-go-15

Go 1.5+, make sure Go 1.4 is installed first.

まず先に1.4をインストールしろとのこと。

ほうほう。

そしてまず公式から再度goをインストール。

$ brew install mercurial //既にインストールされていれば実行しなくても良し
$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
$ export GOROOT_BOOTSTRAP=$GOROOT
$ export GOROOT_BOOTSTRAP=/usr/local/go // 公式からインストールしたgoを通す

いざインストール!

$ gvm install go1.9.2

Installing go1.9.2...
 * Compiling...
go1.9.2 successfully installed!

できた。

以上。

参考にさせて頂きました!

MacOS Sierraでgvmを使ってGo 1.8をセットアップ

【AWS】IAMユーザー&グループちゃちゃっと

AWSアカウントを作成してまずやりたいこと...

ユーザーを作成することですね!はい

IAM

IAM グループ

  1. 新しいグループの作成
  2. グループ名を入力
  3. 任意のポリシーをアタッチする ※ 最初はadminグループを作成したらいいかもしれません。 ポリシーは、AdministratorAccessをアタッチ。
  4. グループの作成 を押下で完了

IAM ユーザー

  1. ユーザーを追加
  2. ユーザー名入力 アクセスの種類で、プログラムによるアクセスAWS マネジメントコンソールへのアクセスを任意で選択 作成しているユーザーで、ログインをする場合は、コンソールのパスワードを設定する。
  3. 当ユーザーへのアクセス権限を付与する グループ既存ユーザー既存のポリシーベースでアクセス権限を付与できる。 あらかじめグループを作成しておくと、管理がし易いでしょう!
  4. あとは確認して、アクセスキー情報をきちんとメモして完了

※ 作成したユーザーを一覧から選択して、認証情報タブを確認すると、コンソールログインのリンクがあるのでそこからログインできるか確認できます。

会社で仕事してるといくつもユーザーがいて、使い分けてるとゴチャゴチャしちゃうので このリンクを抑えておけば問題ないでしょう。

アクセスキーとシークレットアクセスキーは、aws cliというコマンドラインから AWSサービスを制御するかなり重要なツールのためにもしっかりと管理しておきましょう!

f:id:o21o21:20180419172620p:plain

以上

【macOS】Terminalの気になった挙動

かつて使用していたmacbookがあって、久しぶりの起動して整理をしていた。   開発環境も整えようとしてTerminalとかiTermとか色々設定していたのだが、 なんか不自然だなと違和感があった。

環境変数 $TERM

あんまり普段気にしたことなかった$TERMという環境変数が存在する。

この環境変数だが、簡単に言うと、 「アプリケーションが端末の種類を参照するもの」らしい。👀

※ 詳細はここを確認して欲しい。

これがなんだかというと、 私は普段よくvimを使用するのだが、ファイルを開いた後、 :qなどで戻った時に、コンソール上にファイルの跡?編集をしたファイルの形跡が残ってしまう。

いつもはファイルを閉じるとちゃんとファイルが閉じられる。

「なんでだろ~」と思っていたところ、この$TERMがansiになっていたのが原因。

Terminalであれば、Terminalの環境変数からプロファイル→詳細タブ→Terminfoの先頭にあるターミナル宣言方法で変更可能。

f:id:o21o21:20180416215500p:plain

コンソールでは、このように確認できる。

echo $TERM
xterm

※ 変更後は1度ターミナルを終了させないと反映されないっぽい!

xtermにすれば問題なさそうでした!

以上