リモート環境の ipython notebook を使う
参考 wisdomthroughknowledge.blogspot.jp
サーバで:
ipython notebook --no-browser --port=YYYY
クライアントで:
ssh -L -N -f localhost:XXXX:localhost:YYYY HOSTNAME
※ .ssh/config
でHOSTNAMEに対応する key と username は指定済みの場合
ブラウザで localhost:XXXX を開けばOK
NULL と陽に書いていない空なカラムを NULL として取り込ませる @ mysql
会社の人に mysql で csvを読み込むとき,NULL と陽に書いていない空なカラムを NULL として取り込ませる方法を教えて貰った.メモ.
drop table if exists foo; create table foo ( a INTEGER default null, b INTEGER default null ); LOAD DATA LOCAL INFILE 'dat.csv' -- <dat.csv> -- 1,2 -- 3, -- ,4 -- , -- </dat.csv> INTO TABLE foo FIELDS TERMINATED BY ',' (a, @b_raw) set b = case @b_raw when '' then NULL else @b_raw end; select * from foo;
カラム b は一度生データを b_raw という変数で受けて,これが空文字列なら b に NULL をセットするようにしている.a は何も処理していない.
結果:
+------+------+ | a | b | +------+------+ | 1 | 2 | | 3 | NULL | | 0 | 4 | | 0 | NULL | +------+------+
🎉
k番目要素
数列が与えられ,k番目の要素を求めるという問題がある.
解き方としてクイックソートに類似したものがあり,計算時間の期待値は O(n) である.
参考:Spaghetti Source - k 番目の要素の選択
この問題をとく乱択でないアルゴリズムをしった(上記サイトにも解説がある)ので,練習のため実装した. クイックソートライクのアルゴリズムと似ているが,ピボット選択が悪くならないように工夫をしている.
以下コード.ここではkを0はじまりとしている.
#include <cassert> #include <iostream> #include <vector> #include <algorithm> #include <iterator> #include <numeric> template <class T> T calc_k_th_smallest_elem(const std::vector<T>& v, size_t k){ // k in [0, #v) assert(k<v.size()); // Base case, #v <= 10 if(v.size() <= 10){ auto v_copied(v); std::sort(v_copied.begin(), v_copied.end()); return v_copied[k]; } // #v > 10 std::vector<T> mids; mids.reserve(v.size()/5); for(size_t i=0; i<v.size()/5; i+=5){ std::vector<T> mid_candidates; for(size_t j=0; j<5; ++j){mid_candidates.push_back(v[i+j]);} sort(mid_candidates.begin(), mid_candidates.end()); mids.push_back(mid_candidates[2]); } T m = calc_k_th_smallest_elem(mids, mids.size()/2); std::vector<T> lt_m; std::copy_if(v.begin(), v.end(), std::back_inserter(lt_m), [&m](const T& x)->bool{return x<m;}); std::vector<T> eq_m; std::copy_if(v.begin(), v.end(), std::back_inserter(eq_m), [&m](const T& x)->bool{return x==m;}); std::vector<T> gt_m; std::copy_if(v.begin(), v.end(), std::back_inserter(gt_m), [&m](const T& x)->bool{return x>m;}); assert(gt_m.size() + eq_m.size() + lt_m.size() == v.size()); if(lt_m.size() > k){ return calc_k_th_smallest_elem(lt_m, k); } else if (lt_m.size() + eq_m.size() > k){ return m; } else{ return calc_k_th_smallest_elem(gt_m, k - lt_m.size() - eq_m.size()); } }
clang -O2 でコンパイルすると, n = 1億, T = int で6+秒の実行時間でした. Spaghetti Source - k 番目の要素の選択 にもあるように,クイックソート版より実装は複雑である.が,C++11の恩恵もあって,それなりに読める長さになっていると思う.特にラムダ式とcopy_ifが貢献している…気がします.
このコードは「データ構造とアルゴリズム(杉原)」の本アルゴリズムの解説をもとに書き起こしたものです.
- 作者: 杉原厚吉
- 出版社/メーカー: 共立出版
- 発売日: 2001/12
- メディア: 単行本
- 購入: 3人 クリック: 15回
- この商品を含むブログ (3件) を見る
ipython notebook のファイルをダブルクリックで開く:訂正記事
ipython notebook のファイルをダブルクリックで開く方法について以前かいた記事のコードが大幅に間違っていたので訂正します.当該ページは訂正済み.
以前下記の記事を書きました: buq.hateblo.jp
ここで,Automator のシェルスクリプトとして下記のものを使うと書きましたが, この前半(8902ポートの使用状態をみて,必要ならipythonのサーバをたてる) が甚だしく間違っていました.
これで行けると思ってしまったのは,サーバがたった状態で動作を確認していたからです.戸惑わせてしまった方,申し訳ありません😩
正しいコードはたとえば下記のようなものになります:
PORTSTAT_IPYNB=`netstat -tln | grep "8902" | wc -l` if [ "$PORTSTAT_IPYNB" -eq "0" ] then bash -cl 'ipython notebook / --no-browser --port=8902 & sleep .5' > /dev/null 2>&1 sleep .5 fi for f in "$@" do open http://localhost:8902/notebooks"$f" done
解説:
1. PORTSTAT_IPYNB=`netstat -tln | grep "8902" | wc -l`
8902 の使用状態を調べる.0だったらipythonサーバがたっていないとみなして立てる.
2. bash -cl 'ipython notebook / --no-browser --port=8902 & sleep .5' > /dev/null 2>&1
:Automator から直接叩くと怒られるので,bash を立ち上げて,その中で ipython をたちあげる.> /dev/null 2>&1
はなくても動くが,その場合なぜかAutomatorが「プロセスが終わらないよ〜」とずっと歯車アイコンをくるくるさせる.それがうっとおしいので > /dev/null 2>&1
で黙らせる. 参考;Automator workflow "run shell script" keeps run... | Apple Support Communities
整数の除算 @ C++
a/b
とか a%b
の挙動についてメモ.
a
, b
の一方が負である場合は処理系依存(C/C++のバージョンにもよる?)で,
多くの処理系で「実数の割り算の値a/bを0方向に丸める」ということらしい.
ただし (a/b)*b + a%b == a
は成り立つようになっている.
先日書いた 関数オブジェクト @ C++ - buq’s blog について考えていて気になったので.(こちらのコードも修正した)
参考 : - Integer division rounding with negatives in C++ - Stack Overflow - BohYoh.com-C/C++ FAQ 負数に対する除算の結果がおかしいのはどうしてですか。
以下実験コード
#include <iostream> #include <iomanip> #include <vector> #include <numeric> #include <algorithm> #define range(container) container.begin(), container.end() #define say(smth) std::cout << smth << std::endl using namespace std; typedef int (*func_type) (int, int); int mymod(int a, int b){ return a%b; } int mydiv(int a, int b){ return a/b; } // func. name div occupied by C language int mynum(int a, int b){ return (a/b) * b + a%b; } // returns numerator void show_func_result_table(const vector<int> as, const vector<int> bs, func_type f){ cout << "b\\a|"; for(auto && a : as) cout << setw(3) << a; cout << endl; cout << "===="; for(auto && a : as) cout << "==="; cout << endl; for(auto && b : bs){ //if(b == 0) continue; cout << setw(3) << b << "|"; for(auto && a : as) cout << setw(3) << f(a,b); cout << endl; } } int main(){ const int n = 10; vector<int> a(n), b(n); //iota(a.begin(), a.end(), -4); iota(range(a), -4); auto mid_b = b.begin() + (b.end()-b.begin())/2; iota(b.begin(), mid_b, -(n/2)); iota(mid_b, b.end(), 1); say("a\%b"); show_func_result_table(a, b, mymod); say("----------------------------------"); say("a/b"); show_func_result_table(a, b, mydiv); say("----------------------------------"); say("a"); show_func_result_table(a, b, mynum); return 0; }
結果:
bash-3.2$ g++ --version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) Target: x86_64-apple-darwin14.4.0 Thread model: posix bash-3.2$ g++ ./main.cpp -std=c++11 -o main.out bash-3.2$ ./main.out a%b b\a| -4 -3 -2 -1 0 1 2 3 4 5 ================================== -5| -4 -3 -2 -1 0 1 2 3 4 0 -4| 0 -3 -2 -1 0 1 2 3 0 1 -3| -1 0 -2 -1 0 1 2 0 1 2 -2| 0 -1 0 -1 0 1 0 1 0 1 -1| 0 0 0 0 0 0 0 0 0 0 1| 0 0 0 0 0 0 0 0 0 0 2| 0 -1 0 -1 0 1 0 1 0 1 3| -1 0 -2 -1 0 1 2 0 1 2 4| 0 -3 -2 -1 0 1 2 3 0 1 5| -4 -3 -2 -1 0 1 2 3 4 0 ---------------------------------- a/b b\a| -4 -3 -2 -1 0 1 2 3 4 5 ================================== -5| 0 0 0 0 0 0 0 0 0 -1 -4| 1 0 0 0 0 0 0 0 -1 -1 -3| 1 1 0 0 0 0 0 -1 -1 -1 -2| 2 1 1 0 0 0 -1 -1 -2 -2 -1| 4 3 2 1 0 -1 -2 -3 -4 -5 1| -4 -3 -2 -1 0 1 2 3 4 5 2| -2 -1 -1 0 0 0 1 1 2 2 3| -1 -1 0 0 0 0 0 1 1 1 4| -1 0 0 0 0 0 0 0 1 1 5| 0 0 0 0 0 0 0 0 0 1 ---------------------------------- a b\a| -4 -3 -2 -1 0 1 2 3 4 5 ================================== -5| -4 -3 -2 -1 0 1 2 3 4 5 -4| -4 -3 -2 -1 0 1 2 3 4 5 -3| -4 -3 -2 -1 0 1 2 3 4 5 -2| -4 -3 -2 -1 0 1 2 3 4 5 -1| -4 -3 -2 -1 0 1 2 3 4 5 1| -4 -3 -2 -1 0 1 2 3 4 5 2| -4 -3 -2 -1 0 1 2 3 4 5 3| -4 -3 -2 -1 0 1 2 3 4 5 4| -4 -3 -2 -1 0 1 2 3 4 5 5| -4 -3 -2 -1 0 1 2 3 4 5
-1%2
は 1 になって欲しいなあ😩
関数オブジェクト @ C++
C++には関数オブジェクトというものがある.
class に operator()
を適当に定義してやれば作ることができ,
これを用いるとパラメタつき関数みたいなものが実現できる.
ここではパラメタつき比較関数(二つの引数をとって,前者が後者より厳密に小さいときtrue
を返す )を実装している.この比較関数は int
型の「大小」を比較するもので,
パラメタeven_regarded_smaller
がtrue
であれば,偶数は奇数より小さいと判断され,偶奇が一致するものは普通の大小関係で比較される.false
であれば奇数が偶数より小さいと判断され,偶奇が一致するものは普通の大小関係で比較される.
下記のコードはC++11で書かれているので, 古いコンパイラで怒られるようであれば適当な書き換えが必要.
#include <iostream> #include <vector> #include <algorithm> #include <numeric> #define say(smth) std::cout << smth << std::endl using namespace std; class ParityFirstComp{ //static public: static bool is_even(const int& n) {return n%2==0;} static bool is_odd (const int& n) {return n%2!=0;} //n%2 can be -1 static bool have_same_parity(const int& m, const int& n){return (n-m)%2==0;} //non-static private: bool even_regarded_smaller; public: ParityFirstComp(bool even_regarded_smaller): even_regarded_smaller(even_regarded_smaller) {} bool compare_by_parity(const int &l, const int& r) const{ if(even_regarded_smaller) return is_even(l) && is_odd (r); else return is_odd (l) && is_even(r); } bool operator()(const int &l, const int& r) const{ if(have_same_parity(l, r)) return l < r; else return compare_by_parity(l, r); } }; template<class T> ostream& operator<< (ostream& strm, const vector<T>& v){ for(auto&& elm : v) strm << elm << ", "; return strm; } int main(){ vector<int> v(10); iota(v.begin(), v.end(), -4); random_shuffle(v.begin(), v.end()); vector<int> u(v); say("original:"); say(v); say("even_regarded_smaller:"); ParityFirstComp even_first_comp(true); sort(v.begin(), v.end(), even_first_comp); say(v); say("odd_regarded_smaller:"); ParityFirstComp odd_first_comp(false); sort(u.begin(), u.end(), odd_first_comp); say(u); return 0; }
出力は次のようになる.(未ソートの結果はrandom_shuffleの実装に依存すると思う)
original: 6, 0, 3, 5, 7, 8, 4, 1, 2, 9, even_regarded_smaller: 0, 2, 4, 6, 8, 1, 3, 5, 7, 9, odd_regarded_smaller: 1, 3, 5, 7, 9, 0, 2, 4, 6, 8,
それっぽい挙動をしている.
2015/8/23 負の整数にも対応できるよう is_odd
を書き換えた.
ipython notebook のファイルをダブルクリックで開く @ OS X
ipython notebook の .ipynb ファイルをダブルクリックで開きたい人がいます(私です).
他のひともそういうことを考えているみたいです👸
osx mountain lion - Open an ipython notebook via double-click on osx - Stack Overflow
上記のリンクでは Ubuntu ようのシェルスクリプトがのっていますが, OS X の Finder はシェルスクリプトに優しくないのでこのままでは使えません💢✋
この記事では Finder と 上記のスクリプトをつなぐ glue を OS X に付属する Automator で作る…というのをやります😩
やりかた
1. Automator を起動 & 新規ファイルで Application をえらぶ
2. run shell script を左上の検索欄からしらべる
3. このアクション(というのかな?)を右の Application receives files and folders as input
というところの下にドラッグしていきます.勝手に繋がります👺👍✨
右上の pass input:
というところを as arguments
にしておきます.
4. シェルスクリプトを書きます.このスクリプトは osx mountain lion - Open an ipython notebook via double-click on osx - Stack Overflow を改変したものです.ここからはただのシェルスクリプトなので,好きなことを書けばいいです👮 アプリとして適当な場所に保存します.
PORTSTAT_IPYNB=`netstat -tln | grep "8902" | wc -l` #echo "$PORTSTAT_IPYNB" > ~/Desktop/hoge.txt if [ "$PORTSTAT_IPYNB" -eq "0" ] then #bash -cl 'ipython notebook / --no-browser --port=8902 & sleep .5' > /dev/null 2>&1 & bash -cl 'ipython notebook / --no-browser --port=8902 & sleep .5' > /dev/null 2>&1 sleep .5 fi for f in "$@" do open http://localhost:8902/notebooks"$f" done
2015/08/30 Automator で作ったアプリから ipython のサーバを起動させるためには,xdg-open
がopen
になってるのは OS X だからです.他には,for
ループが増えています.それだけです👍ipython notebook
を直接叩くのではなく,bash -cl 'ipython notebook / --no-browser --port=8902 & sleep .5' > /dev/null 2>&1
とせねばならないようです.またif文も間違っていました.これで動いていたような気になっていたのは,すでにサーバが立っている状態で動作を確認していたからです.戸惑わせてしまった方,申し訳ありません.
5. hoge.ipynb とかを適当に選んで右クリック→ Get info で Open with で先ほどのアプリを選びます. info ウィンドウで Change All... を選べばOKです👺👺👺
間違いなど発見したらご連絡ください💫