【Python3】xlsxをcsvに変換する【xlsx2csv】

大量かつ大きめxlsxファイルを同名のままcsvに変換したかったのですが、良い方法やソフトが見つからなかったため自力で行いました。

多分もっとスマートなやり方があるんだろうなと思いつつ、とりあえずメモ。

環境

Mac OSX Yosemite
zsh
Python3

準備

pipでxlsx2csvを入れます。

pip install xlsx2csv

これで恐らくxlsx2csvコマンドが使えるようになったはず。

シェルスクリプト

変換のためのシェルスクリプトを書きます。

files="/path/to/xlsx/dir/*.xlsx"
save_dir="/path/to/save/dir/"

for filepath in ${files}
  do
    filename=`basename ${filepath} .xlsx`
    xlsx2csv -s 1 $filepath $save_dir$filename.csv
  done

-s 1はxlsx2csvのオプションです。
1枚目のシートのみ出力することを意味します。
オプションは適宜設定して下さい。

記述が終わったら、ファイルを適当な場所に保存します。
とりあえずconvert_xlsx2csv.shという名前で保存します。

ちなみに、保存先のディレクトリは存在する必要がある点のみ注意です。

後は保存したファイルに実行権限を与えて、shファイルを実行すれば出力されます。

# convert_xlsx2csv.shのあるディレクトリで
chmod +x convert_xlsx2csv.sh
./convert_xlsx2csv.sh

上手くいけば、csvと化した元xlsxファイルたちが見られるはずです。

【MySQL】新規ユーザーの追加と権限付与

毎回ググるのが面倒なのでメモ。

ユーザーの作成

/* 抽象例 */
CREATE USER some_user@some_host IDENTIFIED BY 'some_password';

/* 具体例 */
CREATE USER hoge@localhost IDENTIFIED BY 'hogehoge';

権限の付与

/* 抽象例 */
GRANT ALL PRIVILEGES ON some_database.some_table TO some_user@some_host IDENTIFIED BY 'some_password';

/* 具体例 */
GRANT ALL PRIVILEGES ON fuga_database.* TO hoge@localhost IDENTIFIED BY 'hogehoge';

データベース内の全テーブルを指定する場合はDB名.*とする。

権限の確認

/* 抽象例 */
SHOW GRANTS FOR some_user@some_host;

/* 具体例 */
SHOW GRANTS FOR hoge@localhost;
...
--  結果省略

【Python3】rdflibの簡単なメモ

日本語Wikipediaオントロジー
上記日本語WikipediaオントロジーのデータをPythonから弄くり回したかったのでrdflibを使いました。

最終的にはファイルサイズが大きすぎて直接的な使用を断念したのですが……。

データの検索部分のみ備忘録的に軽くメモ。
rdfへの要素追加等の操作は特に使用していないので書きません。

インストール

インストールはpipから。

pip install rdflib

完了。

使用方法

初期化

まずは初期化します。

from rdflib import Graph

g = Graph()
g.parse('jwo_instance_rdf.rdf')

グラフの種類は何種類かあるみたいだけれども、とりあえず標準スタイルで。
parseメソッドで読み込むrdfのパスを指定。URLも可能っぽい。
loadというメソッドも用意されているようだけど、リファレンスに記述が無いのでparseとの違いはよくわからない。
ちなみに上記データファイルは1GB近くあるので、パースするのに無茶苦茶時間がかかる。要注意。

検索

要素の検索では、取得したいデータによっていくつかの異なるメソッドが用意されている。
原則としてはどれも同じような使い方をする。

subject,predicate,objectの全てが欲しい場合はtriplesメソッドを使用する。

また、rdflib内に定数が用意されているため、それらを適宜インポートしながら検索条件を指定する。

from rdflib import RDF

for s, p, o in g.triples((None, RDF.type, None)):
    print(s, p, o)

検索条件を指定したい項目のみ引数に値を入れ、他はNoneを指定する。
上記例はsubject,objectは指定無しで、predicateがRDFのtype(http://www.w3.org/1999/02/22-rdf-syntax-ns#type)であるものを条件としている。
引数はsubject,predicate,objectの順にtupleで指定。


その他、返却データが各要素のみであったり(e.g. subjects, objects)、検索項以外の要素のみであったり(e.g. subject_objects)と、いくつかの検索メソッドが用意されている。

# objectデータのみ取得
for o in g.objects(subject=None, predicate=RDF.type):
    print(o)

# subjectとobjectのデータのみ取得
for s, o in g.subject_objects(RDF.type):
    print(obj)

全てのデータが欲しいケースはあまりないと思われるので、中々有用。

検索条件のsubjectにURIを指定したい場合や、objectに文字を指定したい場合は下記のようにする。

from rdflib import URIRef, Literal

# subject項目が下記URIに一致するものを検索
for s, p, o in g.triples((URIRef('http://www.wikipediaontology.org/instance/ゼロの使い魔'), None, None)):
    print(s, p, o)

# object項目がPythonという項目に一致するものを検索
for s, p, o in g.triples((None,  None, Literal("Python"))):
    print(s, p, o)

また、独自のpredicateがrdfデータ内で使用されている場合などは、Namespaceの利用が効率的なようである。
例として、最初に提示した日本語Wikipediaオントロジーで定義されているjwoでの検索を試してみる。

from rdflib import Namespace
JWO = rdflib.Namespace("http://www.wikipediaontology.org/vocabulary#")

for o in g.objects(subject=URIRef('http://www.wikipediaontology.org/instance/ファイナルファンタジー'), predicate=JWO.hyper):
    print(o)

このようにすると、subjectがhttp://www.wikipediaontology.org/instance/ファイナルファンタジーで、predicateがjwo:hyperの要素が抽出される。

結果はhttp://www.wikipediaontology.org/class/『ファイナルファンタジー』となる。

まとめ

rdfの仕組み等を理解していれば容易に利用できるようになっていると思われる。

個人的には、今回初めてrdfデータを扱ったため、最初は勝手がよくわからなかった。
利用してみて、非常に便利な形式だなあと感じた次第。

今回は使わなかったが、rdfの生成の方でも利便性が高そうなので、機会があればまた触ってみようと思う。

参考

Navigating Graphs — rdflib 4.2.2-dev documentation
python rdflibを使う - ラシウラ

夏が終わってた

いつのまにやら8月が終了しておりました。

特に何をしたというわけでもない今年の夏。

強いて起こったことを挙げるならば、昨年の体重増量月間では増やせなかった体重が、今年は増やせました。

ズボンのウエストがキツイという初めての体験。

今年も折り返しを過ぎたので、残りの時間を悔いのないように過ごしたいものです。

【MySQL】後からunique制約を付与する

何度もググっていたので。

alter table some_table add unique (some_field);

ちなみに、複数のフィールドの組み合わせで重複除去したい場合は以下。

alter table some_table add unique (some_field1, some_field2);

参考

MySQL で後からユニークインデックスを追加するには - tilfin's note

シリコーンハイドロゲル素材コンタクトレンズを選ぶ上での自分用まとめ

コンタクトを使い始めてから3年ぐらい経過したわけですが、その間2weekのレンズに関しては一貫して同じものを使い続けてきました。
たまに1dayを使ってはいたものの、コスパ的な問題から殆ど使わなくなりました。

このたびレンズの購入に際して、せっかくなので今までのレンズとは異なるレンズを買ってみようかと調べ出したところ、レンズ事情が想像以上に複雑怪奇だったため、後々のことも考慮してメモしておきます。

レンズの種類

初めに、今回対象とするコンタクトレンズの種類を定義しておきたいと思います。

今回購入の選択肢として挙がっているのは、

という上記3条件を満たしたものとなります。

コストの問題から1dayは不可、また一日の装用時間の問題からシリコーンハイドロゲル素材は譲れない要件です。

レンズ選択のポイント

シリコーンハイドロゲル素材レンズの取捨選択を行う上で注視すべき点は、酸素透過率含水率のようです。
基本的には、酸素透過率は高く、含水率は低いレンズが良いようです。
ただ含水率に関しては装用感にも関わってくるようなので、個人の好みに依存するかもしれません。

現在使用中のレンズ

何はともあれ、現在使用中のレンズについて記しておきます。

メダリスト フレッシュフィット コンフォートモイスト

現在使用しているレンズは、ボシュロム製のシリコーンハイドロゲル素材レンズである、メダリスト フレッシュフィット コンフォートモイストです。

f:id:taka_say:20150712202455j:plain
メダリスト フレッシュフィット コンフォートモイスト|ボシュロム・ジャパン

酸素透過率 含水率
130 36%

初めて眼科を受診した際に処方されたレンズを現在まで継続使用していました。
インターネットでの評判は可もなく不可もなく……といったところでしょうか。
特段良いレンズというわけではなさそうです。
自分としてもそこまでの不満があるわけではないものの、夕刻からの目の乾きが気になるようになってきたこともあり、このたびのレンズチェンジに踏み切ったという感じです。
酸素透過率、含水率ともにシリコーンハイドロゲル素材としては標準的な水準です。

候補のレンズ

当初の3条件を踏まえた上で購入候補をいくつか挙げていきます。

2WEEKメニコン プレミオ

f:id:taka_say:20150712214138j:plain
2WEEKメニコン プレミオ|コンタクトレンズのメニコン

酸素透過率 含水率
161 40%

国産メーカーであるメニコンが販売しているシリコーンハイドロゲル素材のレンズです。
2weekのレンズとしては最高の酸素透過率を誇り、安定した性能が望めそうです。
メニコン!というアナウンスが特徴的なCMもよく目にします。
コンタクトレンズ界のユリウス・カエサルといったところでしょうか。

アキュビュー オアシス

f:id:taka_say:20150712214608j:plain
アキュビュー® オアシス® | アキュビュー®

酸素透過率 含水率
147 38%

お次はJohnson & Johnsonが販売しているアキュビューオアシスです。
ワンデーアキュビュー云々というCMをよく目にします。
酸素透過率は2WEEKメニコン プレミオには及ばないものの、上々の値を保っているようです。
悪くはないですが、これを買うのであれば2WEEKメニコン プレミオでいいような気が。価格差もそこまでないようですし。
どうでもいいですが、Johnson & Johnsonがジョンソネジョンソンに聞こえる感じが好きです。
チャーチル枠。

エア オプティクス EX アクア

f:id:taka_say:20150712214601j:plain
1ヵ月交換終日及び連続装用ソフトコンタクトレンズのエア オプティクス® EX アクア

酸素透過率 含水率
175 24%

脅威の酸素透過率を誇る1monthのシリコーンハイドロゲル素材レンズ。
この高い酸素透過率と、低い含水率から、

エア オプティクス® EX アクアは、その高いクオリティにより、定期交換レンズで初めて、最長1ヵ月の連続装用が承認されたレンズです。 ※眼科医の指導は必要

という意味不明なスペックを誇ります。
一般的な2weekコンタクトレンズと比較すると割高感は否めないですが、それを補って余りある性能を保持しています。
1monthということで、使用途中に紛失・破損等した際のダメージが大きいのは気になるところ。
圧倒的すぎる性能は、女帝エカテリーナを彷彿とさせます。

エアオプティクス アクア

f:id:taka_say:20150712223708j:plain
ツーウィーク(2week)コンタクトのエア オプティクス® アクア | 2週間使い捨てソフトコンタクトレンズのエア オプティクス®

酸素透過率 含水率
138 33%

エア オプティクス EX アクアの兄弟分ともいえるレンズ。
若干含水率が低いこと以外はこれといった特徴はなさそうです。
特筆すべきインパクトがない様が、ビスマルクといったところでしょうか。

バイオフィニティ

f:id:taka_say:20150712214931j:plain
2週間交換コンタクトレンズ バイオフィニティ® |クーパービジョン | コンタクトレンズ

酸素透過率 含水率
160 48%

2WEEKメニコン プレミオに次ぐ酸素透過率を誇るシリコーンハイドロゲル素材レンズです。
含水率がかなり高い点が気になります。
このバイオフィニティ、目に張り付いて取れないことで有名らしいです。
ちなみに2weekということで販売されていますが、米国内で1monthで販売されているレンズと同じ製品らしく、人によっては1month装用する方もいるらしいです。
そのせいかお値段が割高な感じは否めません。
パッケージがバイオな感じなのは好印象です。
なんとなくですが、ワイナ・カパックなイメージのレンズでしょうか。

レンズ性能まとめ

各レンズの酸素透過率と含水率をまとめておきます。

酸素透過率 含水率
メダリスト フレッシュフィット コンフォートモイスト 130 36%
2WEEKメニコン プレミオ 161 40%
アキュビュー オアシス 147 38%
エア オプティクス EX アクア 175 24%
エアオプティクス アクア 138 33%
バイオフィニティ 160 48%

以上、5種類のシリコーンハイドロゲル素材レンズをチェックしました。
あくまで酸素透過率と含水率というデータから判断するならば、バランス重視の2WEEKメニコン プレミオ、装用感重視のバイオフィニティ、目の保全性重視のエア オプティクス EX アクア(リッチ!)といった感じでしょうか。

洗浄液の罠

ところで2weekや1monthのコンタクトレンズでは洗浄が必須ですが、ここに思いもよらぬ罠が潜んでいました。
実はシリコーンハイドロゲル素材のレンズには洗浄液による相性があるらしく、相性の悪いもので洗浄を行ってしまうと、角膜ステイニングが起こってしまうらしいのです。
角膜ステイニングが起こると、角膜障害のリスクが増大してしまうため、可能な限り避けるべきです(許容可能なリスクであるとの指摘もあります)。
というわけで以下がレンズと洗浄液の組み合わせによるリスク表です。
基本的に値が高いほど危険性が高いことを示しています。

f:id:taka_say:20150712234725j:plain
※ エア オプティクス EX アクアは海外名がNight & Dayなため、表最下段のものです。

今我が家にストックされている洗浄液はというと……

f:id:taka_say:20150712235414p:plain

ボシュロム製のレニューです。
2WEEKメニコン プレミオ等は表に記載されていませんが、どうやらレニューは基本的にシリコーンハイドロゲル素材のレンズと相性が悪いようです……。

というわけで……。

まとめ

今回最終的に選ばれたレンズは、レニューと比較的相性の良い、

f:id:taka_say:20150712214931j:plain
バイオフィニティ となりました。
かなりのレニューストックが眠っているという個人的事情から、今回は洗浄液による相性問題が起きてしまうレンズたちは諦めました。

バイオフィニティが自分の目にマッチすることを祈りつつ、ひとまずコンタクトレンズ談義は終了とします。

参考

シリコーンハイドロゲル素材のコンタクト一覧|使い捨てコンタクトレンズ通販ガイド
シリコーンタイプコンタクトレンズ|コンタクトレンズのエースコンタクト
シリコーンハイドロゲル対応のオススメ洗浄液|使い捨てコンタクトレンズ通販ガイド
StainGrid.com

【Python3】データがstrではなくbytesで返ってくる問題【MySQL】

PyMySQL3を使ってDB内のデータ取得をしたところ、varchar型に設定されたカラムのデータがbytes型で返ってきてしまう問題に遭遇。
後々のためメモ。

環境

Python 3.4.3
MySQL 5.6
PyMySQL3

解決策

PyMySQL3への接続とクエリは以下のような平凡なものである。

import pymysql

conn = pymysql.connect(params)
cur = conn.cursor()
cur.execute("SELECT id, name from some_table")
result = cur.fetchone()
print(result['name'])

ここでnameカラムがvarchar型だと、<class 'bytes'>として値が返ってきてしまった。

この問題を解決するためには、DBで定義されているカラムのcollation(照合順序)を変更する必要がある。

現在のcollationを確認するにはmysqlに接続、DBを選択し、

show table status;

を実行すればよい。

Name: some_table
(略)
Collation: utf8_bin

上記のように、collationがutf8_binになっているのがbytes型でデータが返却される原因のようだ。
というわけで下記を実行。

ALTER TABLE some_table COLLATE utf8_general_ci;
ALTER TABLE some_table MODIFY COLUMN name VARCHAR(255) CHARACTER SET `utf8` COLLATE `utf8_general_ci`;

これでカラムの設定と既存のデータがutf8_binからutf8_general_ciに変更された。

pythonに戻り再度実行すると、データがstrで返って来ていることが確認出来るはずである。

参考

python - PyMySQL returns bytes instead of str - Stack Overflow
馬場誠Blog(東京都世田谷区経堂のWebクリエイター)» ブログアーカイブ » 照合順序をutf8_general_ciからutf8_unicode_ciへ変更する

【Python3】HTMLのエスケープされた記号を元に戻す

環境

Python 3.4.3

方法

xml.sax.saxutilsモジュールのunescapeメソッドを使えばOK。

from xml.sax.saxutils import unescape
text = '&amp; &lt; &gt;'
print(unescape(text))  # => '& < >'

第二引数にdictを与えると、独自辞書の定義も可能とのこと。

from xml.sax.saxutils import unescape
text = '&lt;ルイズ貧乳&gt;'
unescape(text, {'貧乳': 'かわいい'})  # => '<ルイズかわいい>'

参考

19.11. xml.sax.saxutils — SAX ユーティリティ — Python 2.7ja1 documentation
236:HTMLをエスケープする

【Python3】sqlite3.ProgrammingError: Incorrect number of bindings supplied【SQLite3】

また引っかかりそうなのでメモ。

環境

Python 3.4.3
sqlite3

解決策

executeメソッドSQLを実行しようとしたところ、

sqlite3.ProgrammingError: Incorrect number of bindings supplied.

と怒られてしまいました。

原因は単純で、executeメソッドの第二引数の形式です。
executeメソッドでは、第二引数はタプルで指定する必要が有るため、以下のようになります。

name = 'some_user_name'

# 駄目な例
c.execute('select * from users where name=?', name)

# 正しい例
c.execute('select * from users where name=?', (name,))

指定する変数がひとつの場合、最後に余計なカンマが付着するため若干気持ち悪いですが、Pythonの文法規則上やむを得ないですね。

【MySQL】データアップデート時に自動で時刻を更新する

フルスタックのWebアプリケーションフレームワークだと自動でやってくれますが、小規模フレームワークだと自力でやらねばならないためメモ。

CREATE TABLE some_tabel (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

これでcreatedには新規に作成された時の時刻が、modifiedにはupdateされる度にその時刻が挿入されます。