end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

Χ(カイ)2乗値と、カイ2乗検定

Χ(カイ)2乗値の定義

 \Large
  \chi^{2} = \frac{(x_1 - m_1)^2}{m_1} + \frac{(x_2 - m_2)^2}{m_2} +
  \cdots + \frac{(x_k - m_k)^2}{m_k}

ただし、x:実測値(観測値)、m:期待値

Χ(カイ)2乗分布表と、グラフ

上側有意確立(p)と自由度(k)に対応するΧ(カイ)2乗値一覧

自由度 p=0.90 p=0.50 p=0.10 p=0.05 p=0.01
1 0.016 0.455 2.710 3.840 6.630
2 0.211 1.386 4.610 5.990 9.210
3 0.584 2.370 6.250 7.810 11.300
4 1.060 3.360 7.780 9.490 13.300
5 1.610 4.350 9.240 11.070 15.100

上表にない自由度や上側有意確立に対応するカイ2乗値は、 インターネット検索等でご確認下さい。

Χ(カイ)2乗分布グラフもインターネット検索等でご確認下さい。

サイコロに対するカイ2乗検定

サイコロを120回振った結果、それぞれの目が10~27回出た場合を 例に2乗値を算出すると、12.4 となります

サイコロの目 x(実測値) m(期待値) x-m (x-m)2/m
1 25 20 5 1.25
2 27 20 7 2.45
3 20 20 0 0
4 10 20 -10 5
5 13 20 -7 2.45
6 25 20 5 1.25
120 120 12.4

ここで、サイコロの自由度が6-1=5 であることより、 Χ(カイ)2乗分布表のp=0.05と比較すると、12.4 > 11.070 である為、 このサイコロは均一でないと言える

/usr/bin/make -j

のように「-j」オプションで、make が早くなるだなんて、知りませんでした。

$ make --help
Usage: make [options] [target] ...
Options:
  -b, -m                      Ignored for compatibility.
  -B, --always-make           Unconditionally make all targets.
  -C DIRECTORY, --directory=DIRECTORY
                              Change to DIRECTORY before doing anything.
  -d                          Print lots of debugging information.
  --debug[=FLAGS]             Print various types of debugging information.
  -e, --environment-overrides
                              Environment variables override makefiles.
  --eval=STRING               Evaluate STRING as a makefile statement.
  -f FILE, --file=FILE, --makefile=FILE
                              Read FILE as a makefile.
  -h, --help                  Print this message and exit.
  -i, --ignore-errors         Ignore errors from recipes.
  -I DIRECTORY, --include-dir=DIRECTORY
                              Search DIRECTORY for included makefiles.
  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.
  -k, --keep-going            Keep going when some targets can't be made.
  -l [N], --load-average[=N], --max-load[=N]
                              Don't start multiple jobs unless load is below N.
  -L, --check-symlink-times   Use the latest mtime between symlinks and target.
  -n, --just-print, --dry-run, --recon
                              Don't actually run any recipe; just print them.
  -o FILE, --old-file=FILE, --assume-old=FILE
                              Consider FILE to be very old and don't remake it.
  -p, --print-data-base       Print make's internal database.
  -q, --question              Run no recipe; exit status says if up to date.
  -r, --no-builtin-rules      Disable the built-in implicit rules.
  -R, --no-builtin-variables  Disable the built-in variable settings.
  -s, --silent, --quiet       Don't echo recipes.
  -S, --no-keep-going, --stop
                              Turns off -k.
  -t, --touch                 Touch targets instead of remaking them.
  -v, --version               Print the version number of make and exit.
  -w, --print-directory       Print the current directory.
  --no-print-directory        Turn off -w, even if it was turned on implicitly.
  -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
                              Consider FILE to be infinitely new.
  --warn-undefined-variables  Warn when an undefined variable is referenced.
  --warn-undefined-functions  Warn when an undefined user function is called.

This program built for x86_64-redhat-linux-gnu
Report bugs to <bug-make@gnu.org>

国土交通省にあるGISデータをPostGISへインポート(2017年版)

先程のエントリの続きです。 postgisの動作確認の為、gisデータをimportし、画像ファイルとして表示します。

mac osx 10.6.3にpostgis, mapserverをinstall - end0tknr's kipple - 新web写経開発

国土交通省にあるGISデータをPostGISへインポート(改訂版) - end0tknr's kipple - 新web写経開発

GISデータのダウンロード & 解凍

http://nlftp.mlit.go.jp/ksj/index.html

上記urlより、行政区域面 (東京 N03-170101_13_GML.zip)をダウンロード。

$ unzip N03-170101_13_GML.zip
$ ls -l
-rw-rw-r-- 1    16232 Mar  4  2017 KS-META-N03-17_13_170101.xml
-rw-r--r-- 1  7497800 Sep  9  2017 N03-170101_13_GML.zip
-rw-rw-r-- 1   472154 Feb 17  2017 N03-17_13_170101.dbf
-rw-rw-r-- 1      145 Feb 17  2017 N03-17_13_170101.prj
-rw-rw-r-- 1  7486656 Feb 17  2017 N03-17_13_170101.shp
-rw-rw-r-- 1    49780 Feb 17  2017 N03-17_13_170101.shx
-rw-rw-r-- 1 18624682 Feb 17  2017 N03-17_13_170101.xml

前回行った際は、 shape形式への変換する必要がありましたが、 既に変換済のデータも提供されるようになったようです。

国土交通省にあるGISデータをPostGISへインポート(改訂版) - end0tknr's kipple - 新web写経開発

shapeファイルから、create table文 , insert文作成、更にimport

$ /usr/local/pgsql/bin/shp2pgsql -p \
  ~/tmp/gis/N03-17_13_170101 gyosei_kuiki > ~/tmp/gis/create_gyosei_kuiki.sql
$ /usr/local/pgsql/bin/shp2pgsql -W cp932 -a \
  ~/tmp/gis/N03-17_13_170101 gyosei_kuiki > ~/tmp/gis/insert_gyosei_kuiki.sql

$ /usr/local/pgsql/bin/psql -U postgres gis_test < ~/tmp/gis/create_gyosei_kuiki.sql
$ /usr/local/pgsql/bin/psql -U postgres gis_test < ~/tmp/gis/insert_gyosei_kuiki.sql

mapファイルの作成と、画像への出力

$ vi gyosei_kuiki.map

MAP
    SIZE 800 800           #画像size
    EXTENT 138.8 35.5 140 36   #出力範囲の座標
    STATUS ON              #地図を表示するか
    UNITS DD               #地図の単位(DD は緯度経度)
    IMAGECOLOR 255 255 255 #背景色R G B
    IMAGETYPE PNG          #地図画像を保存する形式
    LAYER
         NAME "gyosei"
         CONNECTIONTYPE POSTGIS
         CONNECTION "user=postgres password='' dbname=gis_test host=localhost"
         DATA "geom FROM gyosei_kuiki" #select文
         TYPE LINE
         STATUS ON
         CLASS
             COLOR 0 0 0
         END
    END
END

$ /usr/local/bin/shp2img -m gyosei_kuiki.map -o gyosei_kuiki.png

上記のmapファイル作成し、shp2img を実行すると、次のように出力されます。 f:id:end0tknr:20170909131918p:plain

install postgres 9.6 & postgis 2.3 & mapserver & mapserver 7.0

5~6年ぶりに postgres と postgis をinstall.

mapserverがcmakeに対応した点以外では、 しばらく使ってなかった割に変化点は多くありませんでした。

PostgreSQL: The world's most advanced open source database

PostGIS — Spatial and Geographic Objects for PostgreSQL

Welcome to MapServer — MapServer 7.0.6 documentation

mac osx 10.6.3にpostgis, mapserverをinstall - end0tknr's kipple - 新web写経開発

国土交通省にあるGISデータをPostGISへインポート(改訂版) - end0tknr's kipple - 新web写経開発

install postgres

$ wget https://ftp.postgresql.org/pub/source/v9.6.5/postgresql-9.6.5.tar.gz
$ tar -xvf postgresql-9.6.5.tar.gz
$ cd postgresql-9.6.5
$ less INSTALL
$ ./configure
$ make
$ make check
$ su
# make install
# adduser postgres
# mkdir /usr/local/pgsql/data
# chown postgres /usr/local/pgsql/data
# su - postgres
$ /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
$ /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data >logfile 2>&1 &
$ /usr/local/pgsql/bin/createdb test
$ /usr/local/pgsql/bin/psql test

# cd /etc/rc.d/init.d/
# cp /tmp/postgresql-9.6.5/contrib/start-scripts/linux ./postgres
# vi postgres
# chmod 755 postgres
# /sbin/chkconfig --add postgres
# /sbin/chkconfig --list postgres

install postgis

http://postgis.net/source/

Prerequisites

## GEOS
$ wget http://download.osgeo.org/geos/geos-3.6.2.tar.bz2

## Proj.4
wget http://download.osgeo.org/proj/proj-4.9.3.tar.gz

## GDAL
wget http://download.osgeo.org/gdal/2.2.1/gdal-2.2.1.tar.gz

## JSON-C
yum install json-c-devel

postgis

テスト用に gis_test という名称でcreatedb しています。

$ wget http://download.osgeo.org/postgis/source/postgis-2.3.3.tar.gz
$ tar -xvf postgis-2.3.3.tar.gz
$ cd postgis-2.3.3
$ ./configure \
    --with-pgsql=/usr/local/pgsql/bin/pg_config \
    --with-pgconfig=/usr/local/pgsql/bin/pg_config

$ /usr/local/pgsql/bin/createdb -U postgres -E utf8 gis_test
$ /usr/local/pgsql/bin/createlang -U postgres plpgsql gis_test
$ /usr/local/pgsql/bin/psql -U postgres -d gis_test \
    -f /usr/local/pgsql/share/contrib/postgis-2.3/postgis.sql
$ /usr/local/pgsql/bin/psql -U postgres -d gis_test \
    -f /usr/local/pgsql/share/contrib/postgis-2.3/spatial_ref_sys.sql

mapserver

http://mapserver.org/installation/unix.html

Prerequisites

■libpng
$ wget ftp://ftp-osl.osuosl.org/pub/libpng/src/libpng16/libpng-1.6.32.tar.gz

■freetype
$ wget http://download.savannah.gnu.org/releases/freetype/freetype-2.8.tar.gz

■curl
$ wget https://curl.haxx.se/download/curl-7.55.1.tar.gz

■gdal
$ wget http://download.osgeo.org/gdal/2.2.1/gdal-2.2.1.tar.gz
vi include/fcgio.h
#include <stdio.h>   #なにやらerorになったので行追加

■fastcgi
$ wget http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz

■cairo
$ yum install cairo-devel

■harfbuzz
$ yum install harfbuzz-devel

■FriBidi
$ http://fribidi.org/download/fribidi-0.19.7.tar.bz2

■glib*
# yum install glib*
# yum update kernel
# yum update

mapserver

$ wget http://download.osgeo.org/mapserver/mapserver-7.0.6.tar.gz
$ tar xvf mapserver-7.0.6.tar.gz
$ cd mapserver-7.0.6
$ mkdir build
$ cd build
The following options are enabled by default
(version 7.0: WITH_PROJ, WITH_WMS, WITH_FRIBIDI, WITH_HARFBUFF,
              WITH_ICONV, WITH_CAIRO, WITH_FCGI, WITH_GEOS,
          WITH_POSTGIS, WITH_GDAL, WITH_OGR, WITH_WFS,
          WITH_WCS, WITH_LIBXML2, WITH_GIF.)

mapserverのdocumentに上記のようなcmakeのコメントがあったので、 以降は次のように実施。

$ cmake -DCMAKE_PREFIX_PATH=/usr/local/pgsql \
      -DFRIBIDI_INCLUDE_DIR="/usr/include/glib-2.0;/usr/lib64/glib-2.0/include;/usr/local/include/fribidi"  ..
$ make
$ su
# make install

mapservやshp2imgがinstallされたことが分かります

$ ls -l /usr/local/bin
total 176100
-rwxr-xr-x  1 root root    13480 Sep  9 05:41 shptreevis
-rwxr-xr-x  1 root root    18648 Sep  9 05:41 sortshp
-rwxr-xr-x  1 root root    18256 Sep  9 05:41 tile4ms
-rwxr-xr-x  1 root root    18448 Sep  9 05:41 shp2img
-rwxr-xr-x  1 root root    13592 Sep  9 05:41 shptree
-rwxr-xr-x  1 root root    13448 Sep  9 05:41 shptreetst
-rwxr-xr-x  1 root root    14312 Sep  9 05:41 mapserv
-rwxr-xr-x  1 root root    13320 Sep  9 05:41 msencrypt
-rwxr-xr-x  1 root root    13208 Sep  9 05:41 scalebar
-rwxr-xr-x  1 root root    13200 Sep  9 05:41 legend

headless browser(画面なしブラウザ)のphantomjsによる spider & scraping

これまでの「wget –mirror」では、うまくとれないページがあまりに増えてきた為。

PhantomJS | PhantomJS

API | PhantomJS

install

unzip するだけ、ただ、font installは必要

$ su -
# sudo yum -y install gcc gcc-c++ make flex bison gperf ruby \
  openssl-devel freetype-devel fontconfig-devel libicu-devel sqlite-devel \
  libpng-devel libjpeg-devel
$ cd ~/local  
$ wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
$ tar -xvf phantomjs-2.1.1-linux-x86_64.tar.bz2
$ ln -s phantomjs-2.1.1-linux-x86_64.tar.bz2 phantomjs

### https://www.google.com/get/noto/
$ wget https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip
$ su -
# mkdir /usr/share/fonts/noto
# cd /usr/share/fonts/noto
# cp NotoSansCJKjp-hinted.zip
# unzip NotoSansCJKjp-hinted.zip
# chmod 644 *.otf

# fc-cache -fv

sample script

ポイントは、src内にcommentしてます

var system = require('system');
// request urlは引数でも指定ok
var url = system.args[1] || 'http://www.example.com/kodate/chuko/tokyo/list/';
console.log("request url: " + url);

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36';
//for basic auth
page.customHeaders =
    {"User-Agent" : page.settings.userAgent,
     "Upgrade-Insecure-Requests":1,
     "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
     "Accept-Language":"ja,en-US;q=0.8,en;q=0.6",
     "Cache-Control":"max-age=0"
    };

page.viewportSize = { width: 1024, height: 768 };

// for (var atri_key in system.os) {
//     console.log(atri_key +' = '+system.os[atri_key]);
// }


page.open(url, function(status){
    if(status != "success") {
        phantom.exit();
    }
  
    console.log("Status: " + status);

    //page load後に、javascriptが動作してることもある為、sleep
    setTimeout(function(){

        //外部jsのload後の処理にjsonで引数指定ok
        var eval_params = {hoge:"hoge_val"};
        var eval_params_str = JSON.stringify(eval_params);
        var ret = evaluate_list_page(page, eval_params_str);

        console.log(ret['title']);
        console.log(ret['hoge']);
        console.log(ret['last_page']);

        // 一部分の画面キャプチャもok
        page.render('page_all.png');
        page.clipRect = {
            top:    ret['clip_rect']['top'],
            left:   ret['clip_rect']['left'],
            width:  ret['clip_rect']['width'],
            height: ret['clip_rect']['height']
        };        
        page.render('page_part.png');


        for (var i in ret['house_urls']) {
            console.log( ret['house_urls'][i] );
        }

        //htmlの保存
        var fs = require('fs');
        fs.write('page_all.html', page.content, 'w');
        
        phantom.exit();
    }, 5000);
});


//最近のsiteは、jqueryを含んでいることが多い為、実施していませんが
//phantomjsのpage.includeJs() で、外部のjquery等のloadもできます
function evaluate_list_page(page, params_json){
    var ret = page.evaluate(function(params_json) {
        var eval_params = JSON.parse(params_json);
        var ret = {};
    ret['title'] = $('title').text();
    ret['hoge'] = eval_params['hoge'];

        //画面上部にあるpagerから最終pageを取得
    ret['last_page'] = $('.mod-listPaging li.lastPage').eq(1).text();

    ret['house_urls'] = [];

        $('.mod-mergeBuilding--sale .moduleHead h3')
            .each(function(index, element){
                ret['house_urls'].push( $('a',element).attr('href'));
        });

        var clip_rect = $('.mod-mergeBuilding--sale').eq(1);
    ret['clip_rect'] =
            {top:    clip_rect.offset().top,
             left:   clip_rect.offset().left,
             width:  clip_rect.width(),
             height: clip_rect.height()   
            };

        return ret;
    }, params_json);

    return ret;
}

↑こう書いて↓こう実行

$ ~/local/phantomjs/bin/phantomjs --debug=true ./foo2js

xlrd for python で excel (xlsx) を読む

またも、以前のperlでのentryのpython

Spreadsheet::ParseExcelでlinuxのperlからexcelファイルを読む - end0tknr's kipple - 新web写経開発

Mike Blackwell / Spreadsheet-XLSX - search.cpan.org

Douglas Wilson / Spreadsheet-ParseExcel - search.cpan.org

python用 xlsx module は、openpyxl と xlrd の2種類

www.python-excel.org には、 xlrd は xls用と記載されていますが、xlrdも xlsxを読めるようです。

ただ、後述するように数式による値を算出できない場合もあるようですので openpyxl がよいと思います。

http://www.python-excel.org/

openpyxl - A Python library to read/write Excel 2010 xlsx/xlsm files — openpyxl 2.4.9 documentation

xlrd documentation — xlrd 1.1.0 documentation

xlrd/openpyxl for python と Spreadsheet::XLSX/Spreadsheet::ParseExcel for perl の相違点

今回、気づいた範囲では、 数式のあるcellの値を参照した際の返り値が異なっていました。

lang module method 値or数式
perl Spreadsheet::XLSX $cell->value()
perl Spreadsheet::ParseExcel $cell->value() 値 ※1
python xlrd cell.value 値 ※2
python openpyxl cell.value 数式or値 ※3

※1 2017/9/3時点のSpreadsheet::ParseExcelのdocumentを読むと TODOに「Add Formula support」と記載されていました。

※2 後日、xlrd を試していたら、SUM()の値を取得できず、 0となることがありました。

※3 load_workbook(xlsx_path, data_only=True) で開くと、数式でなく値を取得できます

xlrd for python の sample script

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import getopt
import sys
import xlrd

def main():
    xlsx_path = sys.argv[1]
    wbook = xlrd.open_workbook(xlsx_path)
    
    for sheet_name in wbook.sheet_names():
        print '## SHEET_NAME=' + sheet_name
        wsheet = wbook.sheet_by_name(sheet_name)

        for row in range(wsheet.nrows):
            for col in range(wsheet.ncols):
                cell = wsheet.cell(row,col)
                val = cell.value

                if val == None:
                    continue

                print "(%d,%d)=%s" % (row,col,val)

if __name__ == '__main__':
    main()

↑こう書くと↓こう表示されます

## SHEET_NAME=Sheet1
(0,0)=1.0
(0,1)=2.0
(0,2)=3.0
(1,0)=4.0
(1,1)=5.0
(1,2)=6.0
(2,0)=5.0
(2,1)=7.0
(2,2)=9.0

openpyxl for python の sample script

数式がそのまま表示されることが分かります

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
from openpyxl import load_workbook
import getopt
import sys


def main():
    xlsx_path = sys.argv[1]
    wbook = load_workbook(xlsx_path)
    
    for sheet_name in wbook.get_sheet_names():
        print '## SHEET_NAME=' + sheet_name
        wsheet = wbook.get_sheet_by_name(sheet_name)

        row = wsheet.min_row
        row_max = wsheet.max_row
        col_min = wsheet.min_column
        col_max = wsheet.max_column

        while row <= row_max:
            col = col_min
            while col <= col_max:
                cell = wsheet.cell(row=row,column=col)
                
                val = cell.value
                if val == None:
                    col += 1
                    continue
                val_2 = cell.internal_value
                print "(%d,%d)=%s,%s" % (row,col,val,val_2)
                col += 1
                
            row += 1

if __name__ == '__main__':
    main()

↑こう書くと↓こう表示されます

## SHEET_NAME=Sheet1
(1,1)=1,1
(1,2)=2,2
(1,3)=3,3
(2,1)=4,4
(2,2)=5,5
(2,3)=6,6
(3,1)==SUM(A1:A2),=SUM(A1:A2)
(3,2)==SUM(B1:B2),=SUM(B1:B2)
(3,3)==SUM(C1:C2),=SUM(C1:C2)

Spreadsheet::XLSX for perl の sample script

#!/usr/local/bin/perl
use strict;
use warnings;
use Encode;
use Spreadsheet::XLSX;
use Data::Dumper;

main(@ARGV);

sub main {
    my ($xlsx_path) = @_;

    my $wbook = Spreadsheet::XLSX->new($xlsx_path);
    for my $wsheet (@{$wbook -> {Worksheet}}) {
        print "## SHEET_NAME= $wsheet->{Name}\n";
        
        my $row =       $wsheet->{MinRow};
        my $row_max =   $wsheet->{MaxRow};
        my $col_min =   $wsheet->{MinCol};
        my $col_max =   $wsheet->{MaxCol};
        print "RANGE=$row,$row_max,$col_min,$col_max\n";

        while($row<=$row_max) {
            my $col = $col_min;
            while($col<=$col_max) {
                my $cell = $wsheet->{Cells}[$row][$col];
                if(not $cell){
                    $col += 1;
                    next;
                }

                my $val = $cell->value();
                my $val_2 = $cell->unformatted();
                print "($row,$col)=$val , $val_2\n";
                $col += 1;
            }
            $row += 1;
        }

    }
}

↑こう書くと↓こう表示されます

## SHEET_NAME= Sheet1
RANGE=0,2,0,2
(0,0)=1 , 1
(0,1)=2 , 2
(0,2)=3 , 3
(1,0)=4 , 4
(1,1)=5 , 5
(1,2)=6 , 6
(2,0)=5 , 5
(2,1)=7 , 7
(2,2)=9 , 9

python urllib による http getと yahoo ジオコーダapiで、住所→座標(緯度経度)変換

pythonにおけるhttpやjsonの練習の為、以前、perlで書いたentryをpython

geocoding (住所→座標(緯度経度))変換は、google map apiより Yahoo!ジオコーダAPIがよさそ - end0tknr's kipple - 新web写経開発

YOLP(地図):Yahoo!ジオコーダAPI - Yahoo!デベロッパーネットワーク

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import json
import socket
import ssl
import traceback
import urllib
import urllib2

def main():
    # オレオレ証明書のurlにアクセスする場合
    # SSL: CERTIFICATE_VERIFY_FAILED エラーになる為
    ssl._create_default_https_context = ssl._create_unverified_context

    socket.setdefaulttimeout(5);  # sec

    u_agent = urllib2.build_opener()
    u_agent.addheaders = [('User-Agent','python-urllib2-test')];

    api_end_point = 'https://map.yahooapis.jp/geocode/V1/geoCoder'
    params = {
        'appid' : 'ないしょ',
        'output' :'json',
        'ei':'UTF-8',
        "al":4,  #level -> 1=都道府県, 2=市区町村, 3=町/大字, 4=丁目/字
        "recursive": 'true', #見つからない場合、階層上位を探す
        "query": '東京都渋谷区渋谷1-11'
    }

    encoded_params = urllib.urlencode(params)
    req_url = api_end_point + "?" + encoded_params
#    print req_url

    try:
        # openの引数1コはGET, 2コはPOST
        response = u_agent.open(req_url)
    except urllib2.HTTPError as err:
        print("HTTP ERROR "+ err.reason)
        return
    except socket.timeout as err:
        print("SOCKET.TIMEOUT")
        return
    except Exception as err:
        print("UNKNOWN ERROR")
        print traceback.format_exc()
        return
    else:
        pass

    res_all_json = response.read()
    res_all = json.loads( res_all_json )
    res_geocodes = res_all["Feature"]

    for ret_geocode in res_geocodes:
        disp_line = "\t".join([ret_geocode["Geometry"]["Coordinates"],
                               ret_geocode["Property"]["Address"] ]);
        print disp_line

if __name__ == '__main__':
    main()

↑こう書くと、↓こうできます

$ ./foo.py
139.70199214,35.66043257    東京都渋谷区渋谷1丁目

scikit-learn for python による k-means 分類(クラスタリング)

基本的なクラスタリング法ですが、その内容を理解できていない為

k-meansのアルゴリズム

https://ja.wikipedia.org/wiki/K%E5%B9%B3%E5%9D%87%E6%B3%95

wikipediaに記載されている通り

  1. N個のデータに対し、ランダムにK個のクラスタを割り振る
  2. クラスタの重心/中心を算出
  3. 各データ ~ 各クラスタ重心の距離を算出し、最も近いクラスタへ再割り振り
  4. 上記の再割り振りがなくなるまで、上記2 & 3を繰り返す

k-nearest (k近傍法)との違い

名前はk-meansに似ていますが、 k近傍法では、予め用意された点に最も近い距離に分類します。 次のurlが分かりやすいです。 http://qiita.com/NoriakiOshita/items/698056cb74819624461f

pythonでは scikit-learn の KMeans() で

http://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html

install scikit-learn

依存moduleもあるので、pipでinstall

# /usr/local/bin/pip numy
# /usr/local/bin/pip scipy
# /usr/local/bin/pip pandas
# /usr/local/bin/pip scikit-learn

scikit-learn の KMeans() の使用例

http://blog.amedama.jp/entry/2017/03/19/160121 ↑こちらの写経。

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import numpy as np
from sklearn.cluster import KMeans

def main():
    # 3科目の点数
    features = np.array([
        [  80,  85, 100 ],[  96, 100, 100 ],[  54,  83,  98 ],[  80,  98,  98 ],
        [  90,  92,  91 ],[  84,  78,  82 ],[  79, 100,  96 ],[  88,  92,  92 ],
        [  98,  73,  72 ],[  75,  84,  85 ],[  92, 100,  96 ],[  96,  92,  90 ],
        [  99,  76,  91 ],[  75,  82,  88 ],[  90,  94,  94 ],[  54,  84,  87 ],
        [  92,  89,  62 ],[  88,  94,  97 ],[  42,  99,  80 ],[  70,  98,  70 ],
        [  94,  78,  83 ],[  52,  73,  87 ],[  94,  88,  72 ],[  70,  73,  80 ],
        [  95,  84,  90 ],[  95,  88,  84 ],[  75,  97,  89 ],[  49,  81,  86 ],
        [  83,  72,  80 ],[  75,  73,  88 ],[  79,  82,  76 ],[ 100,  77,  89 ],
        [  88,  63,  79 ],[ 100,  50,  86 ],[  55,  96,  84 ],[  92,  74,  77 ],
        [  97,  50,  73 ],
        ])

    # 分類実行 (3個のクラスタに)
    kmeans_model = KMeans(n_clusters=3, random_state=None).fit(features)
    # 表示
    for label, feature in zip(kmeans_model.labels_, features):
        print(label, feature, feature.sum())

if __name__ == '__main__':
    main()

↑こう書くと、↓こう表示されます

$ ./kmeans_scikit_learn.py 
(2, array([ 80,  85, 100]), 265)
(2, array([ 96, 100, 100]), 296)
(0, array([54, 83, 98]), 235)
(2, array([80, 98, 98]), 276)
(2, array([90, 92, 91]), 273)
(1, array([84, 78, 82]), 244)
(2, array([ 79, 100,  96]), 275)
(2, array([88, 92, 92]), 272)
(1, array([98, 73, 72]), 243)
(2, array([75, 84, 85]), 244)
(2, array([ 92, 100,  96]), 288)
(2, array([96, 92, 90]), 278)
(1, array([99, 76, 91]), 266)
(2, array([75, 82, 88]), 245)
(2, array([90, 94, 94]), 278)
(0, array([54, 84, 87]), 225)
(1, array([92, 89, 62]), 243)
(2, array([88, 94, 97]), 279)
(0, array([42, 99, 80]), 221)
(0, array([70, 98, 70]), 238)
(1, array([94, 78, 83]), 255)
(0, array([52, 73, 87]), 212)
(1, array([94, 88, 72]), 254)
(0, array([70, 73, 80]), 223)
(2, array([95, 84, 90]), 269)
(2, array([95, 88, 84]), 267)
(2, array([75, 97, 89]), 261)
(0, array([49, 81, 86]), 216)
(1, array([83, 72, 80]), 235)
(1, array([75, 73, 88]), 236)
(1, array([79, 82, 76]), 237)
(1, array([100,  77,  89]), 266)
(1, array([88, 63, 79]), 230)
(1, array([100,  50,  86]), 236)
(0, array([55, 96, 84]), 235)
(1, array([92, 74, 77]), 243)
(1, array([97, 50, 73]), 220)

apache access_log にあるuser agentからブラウザを判定

昔のエントリのオマージュ。

HTTP User Agentによるブラウザ、OS判定(判別?)なら user-agent-string.info - end0tknr's kipple - 新web写経開発

ssl decryptを行っているロードバランサ(ELB)の配下で 動いているapacheに対し、アクセスしてくるclientのSSL/TLSの対応状況を確認したかった為。

https://help.salesforce.com/articleView?id=000220586&language=ja&type=1

UserAgentString.com - unknown version

に対し、次のscriptのように問合せすれば、OKのはず。

#!/usr/local/bin/perl
use strict;
use warnings;
use Encode;
use HTTP::Request::Common;
use LWP::UserAgent;
use Data::Dumper;

my $REGEXP =
    join(' ',
         '^([^ ]*) ([^ ]*) ([^ ]*) \[([^]]*)\] "([^ ]*)(?: *([^ ]*)',
         '*([^ ]*))?" ([^ ]*) ([^ ]*) "(.*?)" "(.*?)"');

main(@ARGV);

sub main {
    my (@log_files) = @_;

    my $user_agents = collect_user_agent(@log_files);

    my $i = 0;
    for my $user_agent (sort{$user_agents->{$b}<=>$user_agents->{$a}}
                        keys %$user_agents ){
        my $us_short_name = short_name_from_user_anget($user_agent);

        my $access_cnt = $user_agents->{$user_agent};
        print join("\t", $access_cnt, $us_short_name, $user_agent),"\n";
    }
}


sub short_name_from_user_anget {
    my ($user_agent) = @_;

    my $ua = LWP::UserAgent->new;
    $ua->agent($user_agent);
    $ua->timeout(10);

    my $response = $ua->get('http://www.useragentstring.com/');
    unless($response->is_success) {
        die $response->status_line;
    }
    my $html_str = $response->content;

    # scraping が面倒なので、regexp match
    if($html_str =~ /<th colspan='2'>.*?([^<>'=\/]+)<\/th>/o ){
        return $1;
    }
    print STDERR "fail short_name_from_user_anget($user_agent)\n";
    return "";
}

sub collect_user_agent {
    my (@log_files) = @_;
    my $summary = {};
    for my $log_file ( @log_files ){
        open(my $fh ,$log_file) or die "can't open $log_file $!";
        
        while (my $line = <$fh>){
            chomp($line);
            #parse log
            my ($host, $ident, $user, $datetime, $method, $resource,
                $proto, $status, $bytes, $referer, $agent) =
                    $line =~ /$REGEXP/o;
            
            $summary->{$agent} += 1;
        }
        close($fh) or die "can't close $log_file $!";
    }
    return $summary;
}

python srcのオレオレ 雛形(テンプレート template )

たまにしか使わず、忘れるので、これからも追記してくであろうメモ

1枚script

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import getopt
import sys


def main():
    img_file_path = sys.argv[1] # 引数受取り

    # 文字列出力
    print 'バイト文字列で出力'
    print u'UNICODE文字列で出力'

    list = [1,10,100]
    for char in chars_list:
        print "CHAR: %02d" % char  # 変数の文字列展開

def load_csv_file(tsv_file_path):
    csv_rows = csv_read(tsv_file_path, 'shift_jisx0213')
    for row in csv_rows:
        print row[2]
        time.sleep(3)
    return


if __name__ == '__main__':
    main()

potrace による raster (bitmap) to vector

http://potrace.sourceforge.net/

install

$ wget http://potrace.sourceforge.net/download/1.15/potrace-1.15.tar.gz
$ tar -zxvf potrace-1.15.tar.gz
$ cd potrace-1.15
$ ./configure
$ make
$ su
# make install

usage

例えば、以下はインターネットにある間取り画像を image magickのconvertでビットマップ変換し、 potraceで、ベクター(SVG)に変換してます。

$ /usr/local/bin/convert 2ldk.png 2ldk.bmp
$ /usr/local/bin/potrace --backend svg 2ldk.bmp 

他にも autotrace もありますが、installもしていません http://autotrace.sourceforge.net/

inkscapeでも可能で、inkscapeは変換パラメータがいろいろとありました。

pythonでのラプラス変換は sympy の laplace_transform()

微分/積分による計算量を、掛け算/割り算に軽減したかったので、探してみた。

で、pythonであれば、sympyにありました。

http://docs.sympy.org/latest/modules/integrals/integrals.html#sympy.integrals.transforms.laplace_transform

部分積分の導出(証明)と、利用方法

以前の上記エントリとも関連しますが、この手の内容は「部分積分」という名前しか記憶にないので… end0tknr.hateblo.jp

部分積分の公式

 \Large
  \int^b_a f(x) g(x) dx = [ f(x) G(x) ]^b_a - \int^b_a f'(x) G(x) dx

※ただし、  G'(x) = g(x)

導出

積の微分の公式から変形して行きます

 \Large
  \{ f(x)g(x) \}' = f'(x)g(x) + f(x)g'(x) \cdots 式1

上記を積分

 \Large
  f(x)g(x) = \int{ f'(x)g(x) } dx + \int{ f(x)g'(x)} dx

左辺/右辺を移項

 \Large
  \int{ f(x)g'(x)} dx = f(x)g(x) - \int{ f'(x)g(x) } dx
 \Large
  \int^b_a{ f(x)g'(x)} dx = [  f(x)g(x) ]^b_a - \int^b_a{ f'(x)g(x) } dx

最後に、前述の式1に  G'(x) = g(x) を適用し、完了

利用方法

例えば

 \Large
  \int^1_0 e^x x dx = [ e^x \cdot x ]^1_0 - \int^1_0 e^x \cdot 1 dx

openssl主要コマンド一覧 - ssl証明書期限やcipher suite の確認

だいぶ、忘れていたのでメモ

cipher suite の一覧

$ openssl ciphers -v

cipher suite の対応状況

# 対応しているcipher
$ openssl s_client -connect www.google.co.jp:443 -cipher AES256-SHA
# 対応してないcipher
$ openssl s_client -connect www.google.co.jp:443 -cipher AES256-SHA256

ssl証明書の表示と、有効期限確認

$ openssl s_client -connect www.google.co.jp:443 -showcerts
$ openssl s_client -connect www.google.co.jp:443 < /dev/null 2> /dev/null | openssl x509 -text | grep Not

ssl証明書の有効期限確認 (local版)

$ openssl x509 -in /path/to/server.crt -noout -dates