ラベル Python の投稿を表示しています。 すべての投稿を表示
ラベル Python の投稿を表示しています。 すべての投稿を表示
2016年9月24日土曜日

Slack out-going Slash Commands を AWS に設定する(日本語対応済み)

Slackには、Postをトリガーとして、外部へのPush通信を行うことができます。 具体的には、特定の投稿があった場合に、任意のURLに対し、HTTP POSTをします。

ChannelがPublicな場合は、Outgoing WebhookとSlash Commandが使えますが、Privateな場合は、Slash Commandしか使えません。

今回は、Slash CommandをAWSに設定してみました。

参考

Slash Command

  • private channelでもOK
  • internetからアクセスできるSSL(公的)サーバが必要
  • 3秒でレスポンスする必要がある
  • それ以上かかるものは、非同期処理を行う必要がある
  • 返信は、Slash Commandのほか、incoming webhookも使える。

  • Slash Commands Style Guide
  • Set a reminder

AWS上で実装する

今回は、API Gatewayを使ってサーバーレスで構築しました。

API Gatewayを使えば、Slash Commandの要件をそのまま満たすことができるのでオススメです。

処理の流れは以下です。

  • Slack -> API Gateway -> Lambda -> SNS/SQS/Lambda呼び出し等 -> Lambda * N -> Slack

構築方法はこちらが詳しいです。

追加でやったこと

BluePrintが更新されたのか、一部画面が違っていました。

設定順序が変わったレベルだったので、注意して見ながらやれば、問題ないと思います。

IAMロールの設定変更箇所は、直接ポリシーを編集する手順が載っていますが、 ポリシーの追加で簡単に設定することが可能です。

細かいことですが、日本語を使う場合は、Pythonコードの最初に追加します。

# -*- coding: utf-8 -*- 

日本語文字化けの解消

Slash Commandsは、複数行のPostもそのまま引数として渡してくれます。

そのままだと日本語が文字化けします。

最終的に、このような関数を作ってゴリゴリと変換するようにしましたが、よりスマートなやり方がありそうです。

def utf8_in_unicode_to_str(uni):
    chars = list(map(hex, map(ord, uni)))
    res = ''
    for i in chars:
        res += chr(int(i, 16))
    return res

以下調べた内容です。

まず、日本語文字化けの対応として、API Gateway上で設定する例がありました。

ただ、特殊文字(改行など)がエラーになります。

日本語と特殊文字が混在した状態だと、APIgateway上では解決できず、当方、JavaScriptにそれほど詳しくないので、Python側で対応することにしました。

Lambda上で文字列の中身を認するには、[]で囲んでログやレスポンスで渡すのが手軽です。

>>> str = u'あ'
>>> [str]
[u'\u3042']
>>> str = 'あ'
>>> [str]
['\xe3\x81\x82']

Pythonでは、parse_qsした結果をとっていたのですが、そこで、utf-8のバイナリコードがそのままunicodeに入っていました。

#「あ」を渡すと以下のように、unicodeとして入ってしまう。
[u'\xe3\x81\x82']

parse_qsにはencode指定がなかったので、urldecodeから自分でするか、一旦parse_qsでパースしたものに対して、上記関数で、変換することにしました。

サブコマンドを実装

簡単にサブコマンドのパースを実装しました。

import re

# ```は、コードエリアのため、これも区切り文字とする
has_sub = re.search('\s|```', command_text.strip())
if has_sub is None:
    sub_command = ''
    args = command_text.split(' ')
else:
    sub_command = command_text.strip()[0: has_sub.start()]
    args = command_text.strip()[has_sub.start():].split(' ')

pythonで正規表現を使ってみる

2016年9月4日日曜日

Pandas で BigQuery を使うときのメモ

PandasからGoogle BigQueryを使うのは、かなり便利です。 そのときのメモをまとめました。

日付処理

  • BigQueryはUTCです。
  • Pandasのto_datetimeにTimeZone情報を入れる必要がある。
  • 現在の時刻を取る場合

    pd.to_datetime('now').tz_localize('UTC').tz_convert('Asia/Tokyo').to_datetime64()
  • 日本時間を読み取って入れる場合

    pd.to_datetime(datestr, format='%Y年%m月%d日 %H時%M分').tz_localize('Asia/Tokyo').to_datetime64()
  • 扱う方針を決める。
  • UTCに変換する
  • JSTの値をそのまま入れて、タイムゾーンを完全にユーザが管理する

Insert(to_gbq)

  • カラム定義、カラム順など揃える必要がある。
  • 既存のテーブルにto_gbqで、入れるのは調整が手間。
  • 可能なら、最初からto_gbqでテーブルを作った方が良い。
  • 定期的に追加するなら、if_existsを使う。
df.colomns
['gcol2','no_append','gcol1']
# 必要なカラムだけ指定
gdf = df[['gcol1', 'gcol2']]
gdf.to_gbq(table, projectid, private_key, if_exists='append')

pandas からgenerate_bq_schema は使わない

  • スキーマ作成だけ行うgenerate_bq_schemaですが、Duplicateになっています。
  • Creating BigQuery Tables
  • 代わりに上記to_gbqで行います。
  • もしくはbq loadで行います。
  • bq quickstart

import gcpとは

検索すると出てくる

import gcp.bigquery ad bq

これはDataLabの組み込みライブラリです。DataLabから使用します。

2016年8月28日日曜日

GCPのBigQueryを使ってみました

BigQueryを使ってみたので、関連情報をまとめました

GCP NoSQL を使ってデータ処理したい時

主なサービスはこの辺りだと思います。

今回は、格安で比較的枯れているBigQueryを使ってみました。 以降の記事はBigQueryについてです。

オライリー本もあります。 Google BigQuery

課金について

ビッグデータをCloudサービスで使う時、課金方式をよく把握しておくのは必須です。

  • データ保存による: 1TB 1ヶ月 $20
  • スキャンデータ量による
  • BigQueryで150万円溶かした人の顔
  • 300GBに対して、フルスキャンを数百回繰り返した。(テーブル切り分けのために、select insert)
  • 価格体系が今後変わる。computing量による感じに。
  • ストリーミングは課金: 10万行単位などバルクインサートより高い。
  • 費用的には、Cloud Storageなどにデータを置いて、バルクインサートが良い。
  • ストリーミングの方が手間は少ない(Fluentdや、以下のPandasなどで直接インサートできる)
  • ストリーミングはデータ落ちなどが発生する模様。

BigQuery の課金仕様と注意点をまとめてみた(2015-07 時点)

課金対策ツール

使い方

Pythonから使う場合がメインです。

データ分析基盤としての BigQuery 運用のベストプラクティス Python使いのためのBigQuery連携

また、SDKが提供されてない言語でも、REST APIから使えます。 BigQuery クライアント ライブラリ

その場合、OAUTH2認証が必要です。

CLIで使う

Googleが提供している、基本のbqコマンドです。

bq コマンドライン ツール クイックスタート

インタラクティブに使う

GCPのコンソールからのやり方です。

Quickstart Using the Web UI

Jupyter(IPython)ベースのインタラクティブツールもあります。
Betaですが、Jupyterはかなり使いやすいので、こちらもオススメです。

Google Cloud Datalab 上のページのCLOUD DATALAB を起動は使えなくなってる模様。立ち上げはこちらから。dockerを使って起動する。 quickstart

アプリで使う(ライブラリ)

  • Pandas: io.gbqパッケージがあり、read_gbqto_gbqが用意されてます。pandas使っている方ならこれ一択かと。かなり使いやすいです。
  • Pythonのclientライブラリ: BigQuery-Pythonがあります。Pandas使ってない方はこちらが候補になると思います。使いやすいです。
  • 公式API:上記でできないことがある場合以外、直接触ることはないです。ライブラリ作成者向けだと思います。
Pandas

to_gbqinsertすると、ストリーミングになり、課金対象になります。
大量データを入れる場合は計算した方が良いです。

pandas連携が詳しく載ってるので再掲します。

Python使いのためのBigQuery連携 pandas.io.gbq.read_gbq pandas.io.gbq.to_gbq

Python client

BigQuery-Python PythonからBigQueryを操作するときは BigQuery-Python が便利だった

公式API

BigQuery API クイックスタート BigQuery API Client Library for Python getting_started.py Google Application Default Credentials

2016年8月27日土曜日

pandasでの簡単な日付処理

pandasは、日付処理も充実しています。

すぐに使える関数をまとめました。

準備

import pandas as pd

日付に変換

Stringから作成する場合。

> pd.to_datetime('2016-08-26 00:00:00')
Timestamp('2016-08-26 00:00:00')

to_datetimeは、かなり賢く以下のような入力がデフォルトで正しくパースされます。

> pd.to_datetime('2016/8/26 0:0')
> pd.to_datetime('2016/8/26')
> pd.to_datetime('20160826')
> pd.to_datetime('160826 0000')
Timestamp('2016-08-26 00:00:00')

ただし、日付6桁は欧米式にパースされます。

> pd.to_datetime('260816 0100')
Timestamp('2016-08-26 01:00:00')

Python pandas で日時関連のデータ操作をカンタンに

日ごと、月ごと、年ごとに処理

年月日を取り出します。

> pd.to_datetime('2016-08-26 0:0:0').year
2016

> pd.to_datetime('2016-08-26 0:0:0').month
8

> pd.to_datetime('2016-08-26 0:0:0').day
26

dtを使うとdatetime64型の要素のプロパティに直接アクセスできます。

> df['date1']
0   2016-08-26
1   2016-08-27
Name: date1, dtype: datetime64[ns]

> df['date1'].dt.month
8

groupbyする場合です。

# 各カラムを月別に合計
df.groupby(df['date1'].dt.month).sum()

# グルーピングしたデータを取得
df.groupby(df['date1'].dt.month).groups

Python pandas アクセサ / Grouperで少し高度なグルーピング/集計

2016年8月26日金曜日

pandasでmysqlに接続する in debian

ライブラリインストールから、接続までまとめました。

mysql-connector-python + pandas.io.sqlです。

setup

リポジトリからが簡単に入ります。

$  git clone https://github.com/mysql/mysql-connector-python.git
$  cd mysql-connector-python
$  python ./setup.py build
$  sudo python ./setup.py install

condaを使ってる場合です。

$ conda install -c https://conda.anaconda.org/anaconda mysql-connector-python 

ディストリビューションからも取れる模様。

$ sudo apt-get install python3-mysql.connector

参考

python+pandasで大規模データを扱うときのメモ
Python3でMySQLに接続する環境をLinuxで整える
macでのmysql-connector-pythonインストール方法

DataFrameをテーブルから直接作る

import mysql.connector as mc
import pandas.io.sql as pdsql

con = mc.connect(
  user ='USER',
  password='PW',
  host='localhost',
  database='DB')

sql = 'SELECT * FROM table'

df = pdsql.read_sql(sql, con)
# ここでそのまま使えます。

con.close

参考

pandasでRDBの読み書きをする

2016年8月21日日曜日

tensorflow の sample を動かす

以下は、tensorflowの公式チュートリアルの一つ、手書き数字認識のサンプルです。

TensorFlow MNIST tutorial

インストール時にエラーが出る場合があります。 最新版を入れて、protobufを入れ直して解決しました。

インストール

このsampleを試す場合、tensorflowのインストールは、このやり方がオススメです。

少し古いバージョンを直接指定したところ、input_dataのパッケージパスの指定が、tutorialのやり方ではうまくいきませんでした。 また、最新が欲しい方は、githubからcloneする方法もあります。 https://github.com/tensorflow/tensorflow/issues/890

export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.10.0rc0-cp27-none-linux_x86_64.whl
pip install --upgrade $TF_BINARY_URL --trusted-host storage.googleapis.com

データインポート

tutorial に従ってデータをインポートすると以下のようなエラーが出ました。

> from tensorflow.examples.tutorials.mnist import input_data
...
ImportError: Traceback (most recent call last):
  File "/home/YutakaNishimura/tensorflow/lib/python2.7/site-packages/tensorflow/python/__init__.py", line 52, in <module>
      from tensorflow.core.framework.graph_pb2 import *
        File "/home/YutakaNishimura/tensorflow/lib/python2.7/site-packages/tensorflow/core/framework/graph_pb2.py", line 6, in <module>
            from google.protobuf import descriptor as _descriptor
            ImportError: No module named google.protobuf


Error importing tensorflow.  Unless you are using bazel,
you should not try to import tensorflow from its source directory;
please exit the tensorflow source tree, and relaunch your python interpreter
from there.

protobufを確認すると入ってました。
インストールし直しました。

pip uninstall protobuf
pip install protobuf

再度実行すると成功しました。

In [1]: from tensorflow.examples.tutorials.mnist import input_data

In [2]: mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.
Extracting MNIST_data/train-images-idx3-ubyte.gz
Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes.
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes.
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz

Pandasの基本的でよく使いそうな機能のメモ

Pandasの基本的ですが、実際によく使いそうな使い方のメモです。

インストールについて

こちらが非常に詳しいです。 anacondaを使って環境構築します。

Google Compute Engine + Debian で実行しましたが、問題なく動いてます。

データサイエンティストを目指す人のpython環境構築 2016

csv形式のStringからデータを読み取る。

Stringから直接csvデータを読み込むこともできます。 http://stackoverflow.com/questions/22604566/how-to-create-a-pandas-dataframe-from-string

import sys
from io import StringIO

d = StringIO("""a,b,c
1,2,3
11,12,13
""")

df = pd.read_csv(d)

データフレームを連結する

Python Pandasでのデータ操作の初歩まとめ − 前半:データ作成&操作編 pandasでindexの連番を振り直す

concatもしくは、append関数を使います。

行を追加する場合も、DataFrameの連結で行います。

  • concatは対象とするDataFrameをリストにして渡します。
  • appendはdf.appendという書き方になるので、直接行を追加する場合に便利です。
  • どちらもデフォルトでは、非破壊的な動作になっています。

行方向に追加

concatを使って連結

// axis=0 (デフォルト。省略可能)
concated_df = pd.concat([df1, df2])

ちなみに、カラム名が異なると、カラムは全て残り、互いの欠損箇所には、NA値が挿入されます。

欠損値を埋めたい場合は、fillnaを使います。統計処理で必要とされる、平均値補完、線形補間なども簡単にできます。

// 0埋め
df.fillna(0)
// 平均値
df.fillna(df.mean())
// 線形補間
df.interpolate()
// na値削除(行ベース)
df.dropna()
// na値削除(列ベース)
df.dropna(axis=1)

appendを使って行をその場で追加

// columnsを既存のものから取ってきて同じ構造にします
appended_df = df.appned(pd.DataFrame([[1,2,3]], columns = df.columns.tolist())

列方向に追加

pd.concat([df1, df2], axis=1)

同じくインデックスが違うと列方向にNA値が挿入される。

新しい列をその場で追加する方法は、こちらが簡単です。 ただ、dfを直接書き換えるので注意が必要です。

df['c_new'] = [1,2,3]

インデックス・カラムの貼り直し

行番号の貼り直し

concated_df.reset_index(drop=True)

//直接生成時に貼り直すこともできる
pd.concat([df1,df2]).reset_index(drop=True)

カラム名の貼り直し

// dfインスタンスに対して設定
concated_df.columns = ["c1","c2","c3","c4","c5","c6"]

表記ブレをなくすよう変更

// 全て小文字にして、スネークケースにする。記号も開きました。
df.columns = [s.lower().replace(' ', '_').replace('?', '_bool') for s in df.columns.tolist()]

SQLのような処理を行う

よくまとまっていてオススメです。

pandasにsqlでよくやる処理をやらせてみる

sort

sort_valuesを使う方が推奨のようです。

df.sort_values(by="col1")

ERROR

CSVのパースエラー

CSVを読み込む時に、パースエラーが発生しました。

> df = pd.read_csv("file.csv")

pandas/parser.pyx in pandas.parser.TextReader.read (pandas/parser.c:8748)()

pandas/parser.pyx in pandas.parser.TextReader._read_low_memory (pandas/parser.c:9003)()

pandas/parser.pyx in pandas.parser.TextReader._read_rows (pandas/parser.c:9731)()

pandas/parser.pyx in pandas.parser.TextReader._tokenize_rows (pandas/parser.c:9602)()

pandas/parser.pyx in pandas.parser.raise_parser_error (pandas/parser.c:23325)()

CParserError: Error tokenizing data. C error: EOF inside string starting at line 244276

ここで line 244276 は、ファイル上の行数でないので注意が必要です。

この時は結果的に、csvファイルの最終行のデータがおかしくなっていためエラーになっていました。

それでも解決しない場合は、この辺りが参考になると思います。

ISSUEが立っていますが、この問題は現在は、フィックスされてるよう。 https://github.com/pydata/pandas/issues/5501

カラムが多すぎるとExceptionを吐くが、それらを削除して読み込む。

pd.read_csv("file.csv", error_bad_lines=False)

エンコーディングとエンジンを指定する

pd.read_csv("file.csv", encoding='utf-8', engine='c')
pd.read_csv("file.csv", encoding='utf-8', engine='python')

quotingを指定する

import csv
pd.read_csv("file.csv", quoting=csv.QUOTE_NONE)

文字列として読み込んで解析する

f = open("file.csv")
s = f.read()
l = f.readlines()
2016年8月20日土曜日

Pandasで実践的(というか実務的)なデータを扱う

実務的なデータをさっと処理したい場合、

  • SQL
  • スクリプト言語
  • Shell/AWK
  • Excel

あたりがよく使われると思います。

ここでは、スクリプト言語の一つになると思いますが、Python+Pandas紹介します。

Pandasは、Pythonのデータ処理用ライブラリで、DataFrameというExcelのスプレッドシートのようなオブジェクトを使って処理します。DataFrameはもともとS言語/Rに実装されていたものです。

Pandasの特徴である強力で豊富な統計処理の紹介が多いですが、実務データの処理もかなり使えます。

準備

ipython

pythonの対話実行環境としては、ipythonは必須です。 ファイルのタブ補完も効くのでサクサクできます。

pip install ipython

Pandasのimport

ここからは、事前にこのようにimportしていることを前提とします。

import pandas as pd
import numpy as np

データ読み取り

csvファイルの場合。

df = pd.read_csv("a.csv")

URLや桁区切りのカンマにも強いtsvファイルはこちら。

df = pd.read_csv("a.tsv", sep="\t")

ファイルにはヘッダを入れた方がいいです。

PandasのDataFrameはヘッダ情報もきちんと読み取り、列名称で値を指定することが可能なためです。

マージ(join)

現実の業務処理では、joinはかなり需要があると思います。

Pandasももちろんできますが、どちらかというと、統計処理で必要な行を追加していく(union系)の処理の紹介が多いと思います。

Pandasでのマージの仕方。

// キー名が違う場合
merged = pd.merge(df1, df2, left_on = 'id1', right_on = 'id2')
// キー名が同じ場合
merged = pd.merge(df1, df2, on = 'id') 

mergeメソッドは、オプションも豊富です。

行ごとに処理

必要なデータが一つの表にまとまったら、行ごとに処理をしたいですね。

しかもこのロジックはかなり複雑になることがあります。

SQLで複雑なCASE文を書くよりもスクリプト言語で書いた方がすっきりする場合も多いです。

オススメはiterrowsを使うことです。applymapを使うと、関数を渡してシンプルに記述できるのですが、カラム名が使えなくなります。

df['new'] = ""
for key, record in df.iterrows():
  if record["column1"] in ["a", "b"]:
    ...複雑なロジック
    df.loc[key, 'new'] =  "column1 is " + record["column1"]

また、ここはPandasの強力なスライシング処理によって、必要なデータを取得することが可能なのでロジックを簡潔にすることが可能です。

こちらはapplyを使って行ごとに処理する場合。

def f(s):
  print s

df.apply(f, axis=1)

csv/tsvへの出力

非常にシンプルです

csv

df.to_csv("b.csv")

import csv
df.to_csv("b.csv", quoting=csv.QUOTE_ALL)

tsv

df.to_csv("b.csv", sep="\t")

まとめ

各ステップでは、そこに強い言語やツールがあるかと思います。

Python+Pandasは一通り扱えることがメリットだと思います。

一旦、DataFrameに取り込んでしまえば、手続き的な処理、集計処理ともにかなり柔軟に処理ができます。

2016年8月3日水曜日

tensorflow を Debian にインストール

tensorflowをインストールしました。

tensorflowは、Googleが作った機械学習ライブラリです。ティープラーニングに強いことで有名です。

いつもながら、Ubuntuの記事はよく出てきますが、Debianは出てきません。 Debianでも動作することを確認しました。

とりあえずインストール

Ubuntuにとあるが、debianでも問題ない
http://qiita.com/yudsuzuk/items/092c38fee18e4484ece9

virtualenvを使った場合
http://blog.btrax.com/jp/2015/11/29/tensorflow/

virtualenvの使い方
http://www.lifewithpython.com/2013/08/virtualenv.html

SSLエラーが出たとき

Google Cloud Platform の インスタンスからアクセスしたら、以下が出ました。

SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)

以下、SSLエラーを出さないコマンド(--trusted-hostを追加)です

(tensorflow) % pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.5.0-cp27-none-linux_x86_64.whl --trusted-host storage.googleapis.com

よい tensorflow life を!