mecobalamin’s diary

人間万事塞翁が馬

https://help.hatenablog.com/entry/developer-option

WSLでssh

Windows Subsystem for Linux (WSL)から
sshを使ってリモートサーバーにログインする

まず秘密鍵を作ってリモートサーバーに置く

$ ssh-keygen -b 2048
$ ssh-copy-id hogehoge@fugafuga.jp

ログインは

$ ssh hogehoge@fugafuga.jp

なんだけどlocaleのエラーが出る

perl: warning: Please check that your locale settings:
        LANGUAGE = (unset),
        LC_ALL = (unset),
        LANG = "C.UTF-8"
    are supported and installed on your system.

このままだと日本語が文字化けする

WSL その14 - ロケールを日本語に設定する - kledgeb
.bashrcに

export LANG=ja_JP.UTF-8
export LANGUAGE=ja

を追加した

$ locale

を調べると

locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory

がでるので、日本語の言語パッケージをインストール

$  sudo apt install language-pack-ja

これでリモートログイン時のエラーが出なくなった

それと

~/.ssh/config

にホスト名とかを書いておく
インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識 - Qiita

Host fugafuga
HostName fugafuga.jp
User hogehoge
IdentityFile /home/hogehoge/.ssh/id_rsa
$ ssh fugafuga

でログインできるが、
パスワードは必要
秘密鍵おいてあるのだが。。。

iPhoneアプリケーション開発ガイド

図書館行ったらこんな本があった
www.oreilly.co.jp

ちょっと勉強がてらやってみることに。
前準備としてローカルウェブサーバーを立ち上げる。

開発用ローカルサーバを立ち上げる方法 - Qiita
外部からアクセスできるローカルサーバーを立てる | プロカツ!

power shellでindex.htmlをおいたディレクトリに移動し、
pythonのhttp.serverを実行する

> python -m http.server 8080

ちなみにpython3
8080はポート番号

ブラウザからアクセスするにはアドレス欄に

IPアドレス: port番号

でオッケー

iPhoneからもアクセスできた。

WSLでもサーバーは起動できたが
ブラウザからアクセスできず。。。
なんでだろ。
ファイアウォールか何か?

ここも参考になりそう
モバイル Web アプリケーション・フレームワークの比較: 第 3 回 jQTouch で次期モバイル Web アプリケーションを強化する

WindowsでLinux commandを動かす

windowslinuxコマンドが動かせるようになってるらしい
WSL: Windows Subsystem for Linuxという
Windows 10でLinuxプログラムを利用可能にするWSLをインストールする(バージョン1803以降対応版):Tech TIPS - @IT

試してみた

インストールは上のサイトを参考にしたらすぐできた
簡単に手順をまとめてみた

1. [スタート]を右クリック
2. [アプリと機能]をクリック
3. [プログラムと機能]をクリック
f:id:mecobalamin:20190527164215p:plain

4. [Windowsの機能の有効化または無効化]をクリック
f:id:mecobalamin:20190527164243p:plain

5. [Windows Subsystem for Linux]にチェックを入れて[OK]をクリック
f:id:mecobalamin:20190527164316p:plain

6. [今すぐ再起動]をクリック
7. [Microsoft Store]で[wsl]を検索
f:id:mecobalamin:20190527164951p:plain

8. [ubuntu]をインストール。ubuntuを選んだが、ディストリビューションは好みで選んだらいいと思う
f:id:mecobalamin:20190527165009p:plain

9. wslを起動してwslで使用するuser名とpasswordを登録する

ここまででターミナルとコマンドが動く

wslの仕組みは理解できてない
Windows Subsystem for Linux - Wikipedia

ディストリビューション・バージョンはこれ

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic


次は使いやすくするために設定をかえる
こっから先は好みの問題
とりあえずshellはデフォルトのbash
エディタはvimが使いたい
設定は.vimrcを変更する

以前はemacsだったけど
今はwindowsatom使ってるし
wslはvimでいいかと宗旨変え

vimではテキストをコピーしたらクリップボードに入って欲しいけど
そのままではうまくいかないっぽいので.vimrcの編集も含めて以下はメモ

30 March 2019追記

クリップボードを有効化するにはこのあとのメモだけではうまく行かず、
vimコンパイルとVcXsrvのインストールをしている
mecobalamin.hatenablog.com
mecobalamin.hatenablog.com

追記ここまで

bashvimの設定ファイルを編集する
.bashrcはあったが、.exrc/.vimrcはhomeには見つからない
vi/vimともに.exrc/.vimrcを読み込んでる
どちらか一方があればよいのか?

profileの読み込み順はこんな感じらしい
[Linux]環境変数の読み込み順番 - Qiita

".vimrc"の編集
初心者向け vimrcの設定方法 - Qiita
Vimの設定ファイルを作る - Qiita
Vim のカスタマイズ 〜 画面表示の設定 〜 - Vim のブログ

" 行番号の表示
set number
" コマンド行を2行にする
set cmdheight=2
" タブをスペースx2
set tabstop=2
" オートインデント
set smartindent
" 対応するカッコの表示
set showmatch
" カーソル行の表示
set cursorline
" クリップボードにコピー
set clipboard=unnamed,autoselect
" 挿入モードでバックスペースで削除できるようにする
set backspace=indent,eol,start
" コードの色分け
sytanx on
" コメントは黄色(デフォルトは青で黒地には見辛い)
hi Comment ctermfg=6

WSL上のvimでクリップボードを共有する方法 - Qiita

vimクリップボードが使えない。。。
ターミナルにlessを使って表示してコピー
vimからクリップボードにコピーする方法を
書いている人もいるけど、うまくいってない
"+clipboard"になるようにbuildするのも方法っぽい

ubuntu初心者なのでいろいろわからん
[Ubuntu] apt-get まとめ - Qiita
vim-jp » Linuxでのビルド方法

$ git clone https://github.com/vim/vim.git

homeにvimディレクトリができる
configを使ってインストール環境を調べる

$ ~/vim/.git/config

エラーのあるところでとまる

で、コンパイラがないとかなんとかエラーが出てるので
コンパイル環境をインストール

ubuntuでbuild環境を構築
【Ubuntu 18.04 LTS Server】gcc, make などの開発ツールをインストールして使う | The modern stone age.

$ sudo apt install build-essential

こんどはなにかライブラリが足りないって

no terminal library found
checking for tgetent()... configure: error: NOT FOUND!
      You need to install a terminal library; for example ncurses.
      Or specify the name of the library with --with-tlib.

なんでインストール

$ sudo apt-get install ncurses-dev

で、vimのインストール

$ cd ~/vim/
$ ./configure --prefix=$HOME/usr/bin --with-features=huge --with-x=yes --enable-gui=yes --enable-gtk2-check --enable-multibyte -enable-fail-if-missing
$ make
$ make install

やっぱり途中で止まる
ライブラリが足りないみたい

$ sudo apt install libxmu-dev libgtk2.0-dev libxpm-dev

やり直し

$ make distclean
$ rm ~/vim/src/auto/config.cache
$ sudo apt install libxmu-dev libgtk2.0-dev libxpm-dev
$ ./configure --prefix=$HOME/usr/bin --with-features=huge --with-x=yes --enable-gui=yes --enable-gtk2-check --enable-multibyte -enable-fail-if-missing
$ make
$ make install

バージョンの確認

$ vim --version | grep clip
+clipboard         +jumplist          +persistent_undo   +vertsplit
+emacs_tags        +mouse_dec         -sun_workshop      +xterm_clipboard

こうなってればokとのことだけどだけど。。。
クリップボードにコピーできない。。。

一旦ここでペンディング

    • -

19 November 2018追記
コンパイルはできてvimも起動するんだけど、
まだクリップボードには入ってない
なんかvimは仕組みが特殊ぽい

【Linux】クリップボードについて【X Window System】 - Man On a Mission
Vim備忘録 コピペとレジスタ - Man On a Mission

これかな?
https://blog.himanoa.net/entries/20

ベクター形式で保存

これまでグラフはpng形式で出力してきた
あとから編集したりなにかに載せるなら
ベクター形式で出力しておきたい
Scalable Vector Graphics - Wikipedia

ベクター形式を使うことが殆どなく
Illsutratorぐらいしか編集ソフトも知らなかった

Rではsvg形式で出力するパッケージがある
CRAN - Package rvg
Rで解析:プロットをSVGで出力「rvg」パッケージ

こちらの記事の結果をsvgで出力する
mecobalamin.hatenablog.com

パッケージをインストールしてライブラリの読み込み

library("rvg")

この行を

  png.name = sprintf("SD-Hist.png")
  png(png.name, width = 1200, height = 1200)

こう変更する

  svg.name = sprintf("SD-Hist.svg")
  dsvg(file = svg.name, width = 21, height = 21)

出力サイズの問題かpngに比べて9倍ぐらいsvgのファイルサイズが大きい

クラスタリングとヒートマップをexcel形式で出力

Rで結果を出力するときwrite.table()を使って
CSV形式で出力するのが楽だが、
結果をExcelでくれ!ってなる場合もある

それにクラスタリングした結果を並べ替えたり
色を付けなおしたりするにはExcel便利

なので一度Rで計算して結果をExcelファイルに出力する

Excel形式で出力するライブラリがこれ

library(openxlsx)

を使う

例えば前回やったクラスタリングの結果を
Excel形式で出力するときに使っているコードはこちら

WriteClusteringinXlsx <- function(Data.All){

  # 行名の取得
  Sp.Name <- rownames(Data.All)

  # 距離の計算
  Dist.Data <- dist(Data.All, method = "euclidean")
  # クラスタリング
  Clust.Data <- hclust(Dist.Data, method = "ward.D2")

  # クラスタリングの結果に行名を付ける
  Clust.Order <- Clust.Data$order
  Clust.Order <- t(rbind(seq(length(Clust.Order)), Clust.Order))
  Clust.Order <- as.data.frame(Clust.Order)
  colnames(Clust.Order) <- c("num", "hc")
  Clust.Order <- cbind(Clust.Order[order(Clust.Order$hc),], Sp.Name, Data.All)
  Clust.Order <- Clust.Order[order(Clust.Order$num),]
  Clust.Order <- Clust.Order[, c(-1)]
 
  # クラスタリングの履歴をクラスタリングの結果と結合する
  Clust.Height <- cbind(Clust.Data$merge, 
    format(Clust.Data$height, digit = 3, scientific = TRUE))
  Clust.Height <- rbind(Clust.Height, c(NA, NA, NA))
  colnames(Clust.Height) <- c("Element1", "Element2", "Height")
  Clust.Height <- cbind(Clust.Order, Clust.Height)

  # Excel形式での出力
  Excel.Workbook <- createWorkbook()
  Workbook.Name = sprintf("Cluster.xlsx")
  Sheet.Name = sprintf("IRIS")

  addWorksheet(Excel.Workbook, sheetName = Sheet.Name)
  writeData(Excel.Workbook, sheet = Sheet.Name, x = Clust.Height)
  saveWorkbook(Excel.Workbook, Workbook.Name, overwrite = TRUE)

}

Excel形式での出力はまず
createWorkbook()でワークブックを作って、
addWorksheet()でシートを足す
データの書き込みはwriteData()で行う
引数のxが書き込むデータになる
saveWorkbook()で保存してファイルを閉じる
ファイルが開いているとエラーが出る
openxlsx package | R Documentation
RとExcel(ファイルの読み書き、データフレームをExcelで編集) | marketechlabo
R で openxlsx パッケージを用いて xlsx ファイルを扱う - Qiita

pheatmap()でクラスタリングの結果を出力する方法がわからなかったので
dist()とhist()で距離の計算とクラスタリングを行っている
クラスタリング後は種の行の名前がなくなるのでつけ直している
元データは前回と同じでiris

# データの用意
Data.Iris <- iris
Par.List <- colnames(Data.Iris)
Sp.Num <- paste(Sp.Names, rep(1:50, 3), sep = ", ")
d <- Data.Iris[1:4]
rownames(d) <- Sp.Num

# Excel形式で出力
WriteClusteringinXlsx(d)

結果はこちら

hc Sp.Name Sepal.Length Sepal.Width Petal.Length Petal.Width Element1 Element2 Height
1 36 setosa, 36 5 3.2 1.2 0.2 -102 -143 0.00e+00
2 13 setosa, 13 4.8 3 1.4 0.1 -8 -40 1.00e-01
3 2 setosa, 2 4.9 3 1.4 0.2 -1 -18 1.00e-01
~中略~
148 86 versicolor, 36 6 3.4 4.5 1.6 146 147 1.23e+01
149 52 versicolor, 2 6.4 3.2 4.5 1.5 145 148 3.24e+01
150 57 versicolor, 7 6.3 3.3 4.7 1.6

はてな記法で表組みは簡単だけど手間が多い
表組みをつくる(表組み記法) - はてなダイアリーのヘルプ

hcがhclust()のクラスタリングの結果でクラスタリングする前の行番号を表す
行番号が並べ替えられてしまうので種の名前もつけた
Element1/2はクラスタリングの履歴でHeightは距離を示す
R: Hierarchical Clustering

2つの場合はユークリッド距離だけどクラスター同士の計算方法がわからなかった
ヒートマップはExcelでも表示可能
"ホーム" -> "条件付き書式" -> "新しいルール”
で最小値・最大値を数値にすれば同じRと同じように表示できる
f:id:mecobalamin:20180926110023p:plain

Rでクラスタリングとヒートマップ


Rでクラスタリングをしてその結果を
ヒートマップと樹状図で表示するには
pheatmapのライブラリを使う

クラスタリングだけならdist()とhclust()を使えばできるが、
ヒートマップも一緒にとなるとpheatmapかな
https://www1.doshisha.ac.jp/~mjin/R/Chap_28/28.html

他にもあるかもしれないけれど今の所探せてない

ライブラリのインストールは
RGuiの"パッケージ" -> "パッケージのインストール"で行う
CRANのミラーサイトを選んだら
pheatmapパッケージを選択してインストールする

もしくはこのコマンドでインストール

install.packages("pheatmap", dependencies = TRUE)

パッケージ | R のパッケージのインストール方法と呼び出し方

library(pheatmap)
MakingHeatMap <- function(m){

  # pngファイル名
  HeatName = sprintf("heatmap.png")

  # ヒートマップの色の範囲を指定する
  BreaksList <- seq(0, 8.0, by = 1)
  Col.Pal <- colorRampPalette(c("#0041ff", "#ffff99", "#ff2800"))
  Col.List <- Col.Pal(length(BreaksList))
 
  # ヒートマップを描く
  pheatmap(m,
    breaks = BreaksList,
    fontsize = 5,
    color = Col.List,
    cluster_rows = TRUE,
    cluster_cols = FALSE,
    display_numbers = TRUE,
    clustering_distance_rows = "euclidean",
    clustering_method = "ward.D2",
    number_color = "black",
    legend = TRUE,
    legend_breaks = BreaksList,
    legend_labels = BreaksList,
    treeheight_row = 200,
    width = 5,
    height = 10,
    main = sprintf("heatmap"),
    filename = HeatName
  )

出力はpng形式の画像になる
ヒートマップは0から8.0の範囲を1.0刻みで色付けする

pheatmap()の引数は行列
ヒートマップの行方向に樹状図を描くので

cluster_rows = TRUE

距離はeuclidean、クラスタリングの方法はward.D2
hclust()のward.Dは計算方法が間違っていて
ward.D2を使うようにとのことだったが
pheatmap()にも同じ問題があるかどうか未確認
内部でhclust()を呼び出していたら一緒かも

5 October 2019追記
pheatmapのマニュアル読むとhclustと同じ引数を使ってる
https://cran.r-project.org/web/packages/pheatmap/pheatmap.pdf

hclust()のward.Dはward法の実装ではないとのこと
https://data-science.gr.jp/implementation/ida_r_hierarchical_clustering.html

まだはっきりしないけどward法を使う場合は
ward.D2を指定するのが良さげ
追記ここまで


関数はこんなふうに呼び出す

# データの用意
Data.Iris <- iris
Par.List <- colnames(Data.Iris)
Sp.Num <- paste(Sp.Names, rep(1:50, 3), sep = ", ")
#d <- t(rbind(Data.Iris[,3], Data.Iris[,4]))
#colnames(d) <- c(Par.List[3], Par.List[4])
d <- Data.Iris[1:4]
rownames(d) <- Sp.Num

# グラフの作成
MakingHeatMap(d)

結果はこんな感じ

setosaはそれだけでまとまっていて
うまくクラスタリングできているように見える

樹状図のどこかでカットして
3つのグループに分けられれば正解だがどうだろう
1つ目はsetosa, 49とvirginica, 41の間っぽい

virginica, 36とversicolor, 11の間がもう一つの境目に見えるけど
どっちにもvirginicaとversicolorはなんか混じってる
散布図ではそもそもSepalはlength、widthともに
virginicaとversicolorの分離が悪い
petalは分離が良くなるのでpetal.lengthとpetal.widthで
クラスタリングしたのがこちら

versicolor, 47とvirginica, 39の間で分ければ
もう少しマシな感じで3つに分けられそう
散布図で重なっている部分の
クラスタリングが微妙なのかも

散布図との比較で判断したけど
判断の基準があるのかな

ファイルの読み込み

元データが複数あるなら
まとめて処理してくれると便利だ

例えばirisのデータが種類ごとに分かれていて
かつ地域ごとに保存されているとする
chibaとsaitamaの2地域で、3種類に分かれている場合がこれ

180910_Iris-data_chiba_setosa_results.txt
180910_Iris-data_chiba_versicolor_results.txt
180910_Iris-data_chiba_virginica_results.txt
180912_Iris-data_saitama_setosa_results.txt
180912_Iris-data_saitama_versicolor_results.txt
180912_Iris-data_saitama_virginica_results.txt

ファイルの中身はこんな感じ
irisを出力しただけ

"ID","Sepal.Length","Sepal.Width","Petal.Length","Petal.Width","Species"
"1",5.1,3.5,1.4,0.2,"setosa"
"2",4.9,3,1.4,0.2,"setosa"
"3",4.7,3.2,1.3,0.2,"setosa"
"4",4.6,3.1,1.5,0.2,"setosa"
"5",5,3.6,1.4,0.2,"setosa"
~省略~

ファイル名は
"日付_Iris-data_場所_種名_Results.txt"
というフォーマットにする
フォーマットを揃えるのは重要

IDは3つのファイルで通し番号になっているが
個別についていても大丈夫そう

これを前回の関数を使って地域ごとに散布図にしたい
読み込む関数がこちら

ReadFiles <- function(){
    Sp.Files <- list.files() #フォルダ内のファイルのリストを返す

    for(File.Name in Sp.Files){ #ファイルの数だけ繰り返す
    #"日付_Iris-data_場所_種名_Results.txt"
        if(regexpr("_Iris-data[_[:graph:]]*_setosa_results.txt$", File.Name) < 0){
            next
        }
    Split.Name <- strsplit(File.Name, "_") #ファイル名を"_"で分ける

    File.Name.First <- paste(Split.Name[[1]][[1]], Split.Name[[1]][[2]], 
        Split.Name[[1]][[3]], sep = "_")
    File.Name.Second <- Split.Name[[1]][[5]]

    File.Setosa <- paste(File.Name.First, "setosa", File.Name.Second, sep="_")
    File.Versicolor <- paste(File.Name.First, "versicolor", File.Name.Second, sep="_")
    File.Virginica <- paste(File.Name.First, "virginica", File.Name.Second, sep="_")

    Data.Setosa <- na.omit(read.table(File.Setosa, header = TRUE, sep=","))
    Data.Versicolor <- na.omit(read.table(File.Versicolor, header = TRUE, sep=","))
    Data.Virginica <- na.omit(read.table(File.Virginica, header = TRUE, sep=","))

    Label.Name <- c("ID", "Sepal.Length", "Sepal.Width", 
        "Petal.Length", "Petal.Width", "Species")
    colnames(Data.Setosa) <- Label.Name
    colnames(Data.Versicolor) <- Label.Name
    colnames(Data.Virginica) <- Label.Name

    Data.All <- rbind(Data.Setosa, Data.Versicolor, Data.Virginica)
    Data.All <- Data.All[,-1]

    Species.List <- as.character(unique(Data.All$Species))
    Col.Data <- colnames(Data.All)

    MakingSDGraph(Data.All, Species.List, Col.Data[5], 
        Col.Data, Split.Name[[1]][[1]], Split.Name[[1]][[3]])
  }
}

やっていることは

  1. setosa, versicolor, virginicaを1セットとするので、フォルダ内のファイルリストを取得したあとに、リストからファイル名にsetosaが入るファイルを正規表現で探す
  2. 次にsetosaと、対になるversicolor, virginicaのファイル名を作り、read.table()で読み込む
  3. そしてcolnames()でカラム名を揃えてデータを結合する

regexpr()はパターンマッチを行う関数で引数に正規表現が使える
文字列 | R で文字列の切り出しや置換などの文字列処理を行う方法
R における正規表現 - RjpWiki

ReadFiles()から前回の関数MakingSDGraph()を呼び出して
結合したデータを前回と同じように処理をする

MakingSDGraph()は引数が2つ増えている
これは出力ファイルに元ファイルの日付と地域名を入れるための変更
関数にも一部変更を加える

MakingSDGraph <- function(data.all, sp.list, col.name, col.list, sample.date, sample.location){

  # データごとの色の定義
  data.color <- data.all[col.name]

  # グラフを書き込むファイルの用意, 5x5の領域を確保する
  png.name = sprintf("SD-Hist_%s_%s.png", sample.date, sample.location)

出力されたファイルには元ファイルの日付と地域名が入っている

SD-Hist_180910_chiba.png
SD-Hist_180912_saitama.png

グラフは前回と一緒なので省略