OmniAICreator/Qiita-1.07M huggingface dataset:
coreNFCを使いバックグラウンドでNFCタグを読み取れるか

案件でNFCタグをアプリを起動せずに読み込めるかどうかを検証したので、
備忘録として。

## 動作環境
- Xcode10.1
- iPhoneXS

## iPhoneXS以降
URLタイプのNFCタグであればアプリがなくてもタグを読み込むことが可能。
Universal Linksを使うことで特定のアプリを開くことも可能なので
いろいろなことができそう。

ただし、端末がOFFのとき・カメラが起動されているときは
NFCタグを読み込むことができない。

## iPhone7 ~ iPhoneXまで
NFCタグを読み込むためには、アプリが必要。
下記サンプルソースでログにNFCタグに書き込んだ内容を取得することが可能。

## サンプルソース
```swift
import UIKit
import CoreNFC

final class ViewController: UIViewController {

    private var session: NFCNDEFReaderSession?

    override func viewDidLoad() {
        super.viewDidLoad()
        // NFCの利用制限確認
        if NFCNDEFReaderSession.readingAvailable {
            // invalidateAfterFirstReadは連続でNFCタグを読み込むかどうか（true : 一回 false: 複数回）
            self.session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
            self.session?.alertMessage = "NFCタグをiPhoneに近づけてください" 
            // 読み取り開始
            self. session?.begin()
        } else {
            print("❎端末的に使えないよ❎")
        }
    }
}

extension ViewController: NFCNDEFReaderSessionDelegate {
    /// 読み取りエラーが起こった時呼ばれる。ユーザーがキャンセルボタンを押すか、タイムアウトしたときに呼ばれる。
    func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        print("Error: \(error.localizedDescription)")
        print("🙅‍♂️エラー")
    }

    /// 読み取りに成功したら呼ばれる。
    func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
        for message in messages{
            for record in message.records {
                print(String(data: record.payload, encoding: .utf8))
                print("👌読み取ったよ")
            }
        }
    }
}
```

## まとめ
iPhoneXS以降の端末であればアプリを起動していなくても、URLタイプのみNFCタグを読み込むことができるが、
画面がオンの状態じゃないといけないのが難点かもしれない。
また、iPhone7～iPhoneXまでは別途アプリが必要なので、今のところはバックグラウンドでNFCタグを読み込むのは
限定的すぎて現実的ではなさそうでした。

## 参考記事
- [iOS11 Core NFCを使ってみた](https://qiita.com/SatoTakeshiX/items/cd3b8908c96e4391a475)
テキストリンクの表示切替

HTMLで表示したテキストリンクを状態に合わせて表示を変える方法について。

#リンクの色を変える
適用するHTMLのコード

```linkstyle.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="linkstyle.css">
<title>テキストリンクの色を変える </title>
</head>
<body>
	<p>こちらはQiitaのホームページです→<a href="https://qiita.com/">Qiita</a></p>
</body>
</html>
```
HTML自体の表示は↓のようなかんじです（実際にはリンク部分に下線あり）
><p>こちらはQiitaのホームページです→<a href="https://qiita.com/">Qiita</a></p>

これに次のCSSを適用します。

```linkstyle.css
@charset "utf-8";
body {
    font-family: sans-serif;
    font-size: 21px;
}

a {color: #0073bc;}
a:link {color: #0073bc;}
a:visited {color: #02314c;}
a:hover {color: #b7dbf2;}
a:active {color: #4ca4e8;}
```
ただし、このCSSの上部分

```linkstyle.css
@charset "utf-8";
body {
    font-family: sans-serif;
    font-size: 21px;
}
```
　この部分はこの記事には直接関係ありませんがCSS全体の設定やフォントの設定を書いています。

`<a>`のタグのスタイルがこの記事のメインです。

```linkstyle.css
a {color: #0073bc;}
a:link {color: #0073bc;}
a:visited {color: #02314c;}
a:hover {color: #b7dbf2;}
a:active {color: #4ca4e8;}
```
　このCSSでは`<a>`の4つの**疑似クラス**について設定しています。

>CSS の擬似クラスPseudo-classesは、セレクターに付加するキーワードであり、選択された要素対して特定の状態を指定します.


`a {~}`はここでは設定しなかった疑似クラス適用する色を設定しています。
ここで設定している色はこんな感じ→<font color="RoyalBlue">Qiita</font>

`a:link {~}`では`<a>`中でもhref属性がついたタグのみに適用されます。
ここで設定している色はこんな感じ→<font color="RoyalBlue">Qiita</font>

`a:visited {~}`では`<a>`でリンク先が訪問済みのときに適用されます。
ここで設定している色はこんな感じ→<font color="MidnightBlue">Qiita</font>

`a:hover {~}`はその要素がホバー状態のときに適用される。
ここで設定している色はこんな感じ→<font color="PowderBlue">Qiita</font>

`a:active {~}`その要素上でマウスがクリックされているとき適用される。
ここで設定している色はこんな感じ→<font color="DodgerBlue">Qiita</font>

※このスタイルを適用する順番はこの順番に書かないとうまくいかないことがあるようです

#リンクの下線の表示切替
適用するHTMLのコード（先ほどのものとリンク先のCSSが違うだけです）

```linkstyle2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="linkstyle2.css">
<title>テキストリンクの色を変える </title>
</head>
<body>
	<p>こちらはQiitaのホームページです→<a href="https://qiita.com/">Qiita</a></p>
</body>
</html>
```
で適用されるCSSがこれ↓です。

```linkstyle2.css
@charset "utf-8";
body {
    font-family: sans-serif;
    font-size: 21px;
}

a {text-decoration: none;}
a:hover {text-decoration: underline;}
```

`a {text-decoration: none;}`で通常時のリンクでは下線の表示を消し、`a:hover {text-decoration: underline;}`要素がホバー状態の時した線を表示するという感じにしています。


色の表示と下線の表示切替は同時に適用もできます。


#参考文献
[書籍『いちばんよくわかるHTML５&CSS3デザインきちんと入門』](https://www.sbcr.jp/products/4797388541.html?sku=4797388541)
[MDN web docs 「疑似クラス」](https://developer.mozilla.org/ja/docs/Web/CSS/Pseudo-classes)
[ホームページの作り方 リンクのCSS -「a:hover」と「a:visited」](https://www.homepage-tukurikata.com/css/a-css.html)
Rustのイテレーターさっぱり分からん☆（＾～＾）

ファイルの先頭行だけ読みたいというときに

```rust
for result in BufReader::new(File::open("test.txt").unwrap()).lines() {
    let first_line = result.unwrap();
    println!("Read line: `{}`.", first_line);
    return first_line;
}
```

みたいな感じでループを回そうものなら、このループは１回しか実行されないと `clippy` に指摘されてしまう。
だったら　どうすればいいのか？

```rust
if let Some(first_line_result) = BufReader::new(File::open("text.txt").unwrap()).lines().next() {
    let first_line = first_line_result.unwrap();
    println!("Read first line: `{}`.", first_line);
    first_line
} else {
    "".to_string()
}
```

`.lines()` というのが `Iterator` を返すようなので、ループに渡す代わりに `.next()` を１回だけ実行すればいいのか。
イテレーターの使い方とか　必修だな。
pandas インデックスの操作についてのメモ（記述途中）


# はじめに

```python:サンプルのDataFrame

testdf = pd.DataFrame({ 'id' : 1.,
                        'name' : pd.Categorical(["joseph","jotaro","jorin","jonathan"]),
                        'time' : pd.Timestamp(datetime.datetime.now()),
                        'f_num' : pd.Series(1,index=list(range(4)),dtype='float32'),
                        'i_num' : np.array([3] * 4,dtype='int32'),
                        'sex' : ["male","male","female","male" ]  ,
                        "part_num" : [2,3,6,1]})


>testdf

	id	name	time	f_num	i_num	sex	part_num
0	1.0	joseph	2019-03-31 16:51:43.383692	1.0	3	male	2
1	1.0	jotaro	2019-03-31 16:51:43.383692	1.0	3	male	3
2	1.0	jorin	2019-03-31 16:51:43.383692	1.0	3	female	6
3	1.0	jonathan	2019-03-31 16:51:43.383692	1.0	3	male	1

```

# indexをまとめて変更する

### columns.map(index.map)による操作

```python

testdf.columns = testdf.columns.map(str.title)
testdf

# title関数により単語の先頭が大文字になります。
Id	Name	Time	F_Num	I_Num	Sex	Part_Num
0	1.0	joseph	2019-03-31 16:51:43.383692	1.0	3	male	2
1	1.0	jotaro	2019-03-31 16:51:43.383692	1.0	3	male	3
2	1.0	jorin	2019-03-31 16:51:43.383692	1.0	3	female	6
3	1.0	jonathan	2019-03-31 16:51:43.383692	1.0	3	male	1

```


### rename関数による操作（引数として関数を渡す）

```python

testdf.rename(columns=str.upper, inplace=True)
testdf

	ID	NAME	TIME	F_NUM	I_NUM	SEX	PART_NUM
0	1.0	joseph	2019-03-31 16:51:43.383692	1.0	3	male	2
1	1.0	jotaro	2019-03-31 16:51:43.383692	1.0	3	male	3
2	1.0	jorin	2019-03-31 16:51:43.383692	1.0	3	female	6
3	1.0	jonathan	2019-03-31 16:51:43.383692	1.0	3	male	1
```

```python
# 列名、index名、まとめての変換もできる。
testdf = testdf.rename(columns=str.upper,index=str.lower)
``` 

# 部分変更
### rename関数による操作（引数として辞書を渡す）

```python

testdf.rename(columns={"Time":"Datetime"},inplace=True)
testdf

	Id	Name	Datetime	F_Num	I_Num	Sex	Part_Num
0	1.0	joseph	2019-03-31 17:16:43.683755	1.0	3	male	2
1	1.0	jotaro	2019-03-31 17:16:43.683755	1.0	3	male	3
2	1.0	jorin	2019-03-31 17:16:43.683755	1.0	3	female	6
3	1.0	jonathan	2019-03-31 17:16:43.683755	1.0	3	male	1
```

# Multi_index

こちら、まだよくわかりません。
データを読み込み後にマルチインデックス化する方法についてはまだ勉強中のため、のちほど追記予定です。読み込みの時に元データがマルチインデックスっぽくなってたら下記のように取込ができました。

### データの読み込み時にマルチindexのレベルと使用する列・行を指定する方法

```python

# マルチindexとして、0行目と1行目をheaderとして使用する。
df = pd.read_excel("hoge.xlsx",header=[0,1])

# マルチindexとして、0列目と1列目をindexとして使用する。
df = pd.read_excel("hoge.xlsx",index_col=[0,1])

```
React: import時のaliasを設定するときはWebpack、TypeScript、ESLintの3つを対応しなければならない件

ReactとTypeScript & ESLintで開発するのがここ最近好き。[tslintさようなら、@typescript-eslintこんにちは](https://teppeis.hatenablog.com/entry/2019/02/typescript-eslint)。

そんな中でaliasを設定しよう思ったとき、三カ所も設定する必要があったので覚え書き。

以下、想定としては、ルート直下に`/src`があって、それに対するaliasを`~/`で書きたいというもの。Nuxtっぽい感じ。
ex) `import Awesome from '~/components/Awesome';`

# 1. Webpack の resolve.alias

[公式](https://webpack.js.org/configuration/resolve/#resolvealias)にもある通り、まず何よりバンドルする際にきちんと認識してもらわないと始まらない終わらない。

```webpack.config.js
  resolve: {
    alias: {
      '~': path.resolve(rootPath, '/src'), // rootPath にはルートのパスが入る。
    },
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
  },
```

# 2. TypeScript としての alias

[`tsconfig.js`にも設定する必要がある](https://qiita.com/nju33/items/cf924f7b6bb513bef8a2)。

```tsconfig.js
{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "~/*": ["src/*"]
    },
```

この際、"baseUrl"が必要なのと、`"~/*`のように正規表現的な書き方をする必要がある点に注意。

# 3. ESLint の import alias

これだけ、全然想定していなかった。勝手には判断してくれなかった。

まぁ調べてみたら、[`eslint-import-resolver-webpack`](https://www.npmjs.com/package/eslint-import-resolver-webpack)を導入して、[settingsに書くだけ](https://github.com/webpack-contrib/eslint-loader/issues/103#issuecomment-277485181)であった。

```.eslintrc.js
  settings: {
    react: {
      version: 'detect',
    },
    'import/resolver': {
      webpack: { config: path.join(__dirname, '/config/webpack.config.js') },
    },
  },
```

ちなみに、Webpackを使用しないプロジェクトの場合、[`eslint-import-resolver-typescript`](https://github.com/alexgorbatchev/eslint-import-resolver-typescript) packageをインストールした後、`settings`の`'import/resolver'`に`typescript: {},`を追加して typescript のサポートを有効化する必要がある。

```.eslintrc.js
'import/resolver': {
  node: {
    extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
  },
  typescript: {},
},
```
Google Play Developer アカウント間でアプリを移行する際の留意事項

# 概要
Google Play Developerアカウント間でアプリを移行する際のメモ書きです。

# 手順
基本的に下記サイト解説に従って順番に進めていけば大抵の場合は問題なく移行はできそうです。
[別のデベロッパー アカウントへのアプリの移行](https://support.google.com/googleplay/android-developer/answer/6230247?hl=ja&ref_topic=3450986&visit_id=636896296388607684-916063070&rd=1)

Google Playに公開しているアプリしか移行をしたことはありませんが、App Storeのアプリ移行よりもGoogle Playの方がアプリ移行の整備がされている印象。

## アプリ移行の前に確認および準備する事柄
・移行するアプリがポリシー違反をしていないかの確認
・売り上げレポートおよび収益レポートは移行されないのであらかじめエクスポートしてダウンロードしておく
・移行先のアカウントが「**有効**」な状態になっているかどうか
※アカウント作成のみでなく、アカウントの有効化を行なっている必要があります。(25ドルの登録料の支払い等)

## 移行
アプリの移行画面です。
<img width="973" alt="スクリーンショット 2019-03-31 20.59.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/66341/77c72f4b-81c7-72f0-7f6d-fe162e7435e7.png">
実際の移行画面のURLは下記。
https://play.google.com/apps/publish/#AppTransferPlace

必要な主な項目は下記です。

・現所有者の氏名
・移行先のアカウントのメールアドレス
・移行先のPlay Consoleアカウントの注文ID

Play Consoleのアカウントの注文IDとは、Play Consoleアカウント登録時に支払った登録料の領収書が送られてくるメールと一緒に記載があります。メールを遡って、注文IDを確認しましょう。
メールが見つからない場合、[Google Payments](https://payments.google.com/payments/home)の「定期購入とサービス」から確認をすることも可能です。

以上が手順のメモ書きになります。

#注意事項
## 課金アイテムのあるアプリの移行
これは実際に体験した落とし穴ですが、移行先アカウントがPlay Consoleアカウントの登録が完了していても、「お支払いプロファイル」が設定されていない場合は先に対応が必要です。

支払いプロファイルが設定されていないアカウントは、こんな感じの画面になっているはずです。
<img width="1333" alt="スクリーンショット 2019-03-31 21.13.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/66341/ee65f4a7-1b25-cd53-14aa-049214cdd02e.png">

その場合は、先に移行先アカウントの支払い設定を完了させましょう。
注意としては、移行先アカウントに支払い設定が完了していなくても、課金アイテムを含むアプリは移行ができてしまう点です。
そのため、アプリは移行したが課金コンテンツの支払いプロファイルが移行元のままになってしまうという状況があり得ます。
支払い設定は手間がかかる作業なので、余裕を持って前もって行なっておきましょう。

## Firebaseアカウントの移行

移行元のPlay Consoleアカウントに紐づいているFirebaseアカウントはあらかじめリンクを解除しておき、新たに移行先のアカウントに紐付けを行いましょう。

## 別途アプリのリリースが必要な場合もある
アカウントの移行に伴ってアプリ自体のリリースが必要な場合があります。
例えば、Admobを利用しているアプリの場合、アプリ内で設置しているAdmob広告の設定を移行先の適切なアカウントのものに切り替え、再度リリースをする必要があります。
Admobに限らず、SDKを利用しているものの多くはリリースをしないとアカウント移行できないケースが多くあると思います。
リリースが必要な項目を洗い出しておき、なるべく少ないリリースでアカウントの移行を行うべきです。

## 移行リクエスト送信後の公開
移行リクエスト送信完了後、2日営業日ほどでサポートチームの担当の方から連絡が届きます。
連絡の中には、移行したアプリの登録によっては丁寧に下記のような注意を記載してくれます。

```
移行の完了に伴い、以下の点にご注意ください。

- システムの記録によると、アプリは Google Cloud プロジェクト（ゲームサービスなど）に統合されています。
そのため、Google Developers Console を使って移行先のアカウントの権限を追加する必要があります。
詳しくは、ヘルプセンターの記事をご覧ください。

- システムの記録によると、アプリは統合版の広告 SDK を使用しています。
該当するアカウントに広告トラフィックのクレジットが関連付けられるようにするため、広告 SDK の統合を APK で更新する必要があります。

- システムの記録によると、AdWords アカウントがお客様の Google Play Developer アカウントにリンクされています。
このアプリの所有者は新しいアカウントに変わったため、今までのアカウントを使用してこのアプリのユーザーをターゲットに設定することはできなくなります。
AdWords アカウントを使用して引き続きこのアプリのユーザーをターゲットに設定する場合は、新しいアカウントから新たにリンクしてください。

- 今までのデベロッパー アカウントの閉鎖と払い戻しをご希望の場合は、このメールに返信してその旨お知らせください。
元のアカウントをキャンセルしてデベロッパー登録料を払い戻しいたします。
```

前もって用意をしておくべきですが、サポートチームからのメールでも必要な項目が洗い出せるので、未対応の項目がある場合はこの段階で対応してしまいましょう。
移行後はそのまま移行先のアカウントで公開がされます。(公開を手動で行うことはなかった認識です。)
移行先アカウントの所有者とタイミングを合わせて実施しましょう。

以上、簡単ではありますが、Google Playに公開しているアプリの移行に関するメモ書きでした。
Oracle Database 導入編

### Oracle Database
現場でOracle使ってるので、勉強がてらまとめてみました。

Oracle Databaseは有償のRDBMSです。実際にシステムに導入する場合はお金払って購入する必要がありますが、個人の学習用に無償でダウンロードできるのて、実際に自分のPCにインストールしてちょこちょこいじってみました。

## Oracle Database ダウンロード
Oracle DatabaseはOracleの公式技術情報サイトからダウンロードできます。
↓
[公式技術情報サイト](https://www.oracle.com/technetwork/jp/index.html)

その際に
・Oracle.comのユーザー登録
・OTNライセンス同意書への同意※
の2点が必要となります。
※OTNライセンスとは、自社内または個人でのアプリ開発やテスト、デモンストレーション等の目的であれは無償で使える限定ライセンスです。詳細は公式サイトを参照。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/ef607904-3941-e242-bb5d-a10fcaf17edf.png)
ライセンスに同意するにチェックを入れるとダウンロード可能になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/cd861d7a-8cfa-1109-8310-e0ce15c3b8f8.png)

今回は「Oracle Database 12c Release 2」をインストールしてみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/9e1ebd1f-60c2-d373-5878-b8a0558e0830.png)

ダウンロードしたら任意のフォルダに解凍して、その中の「setUp.exe」を管理者として実行します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/880adb3d-f2fc-e005-7037-680716121961.png)

コマンドプロンプトの画面が表示された後に
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/3dbd0066-ac6e-a5d2-50e5-547da3bcdb33.png)
インストーラーが起動します。
最初の画面ではセキュリティ関連の情報を受け取るメールアドレスの登録を促されますが、ここは必須ではないです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/16001974-7549-91b8-ca8e-6a5a3909d356.png)
チェックを外して進むと警告が出ますが、そのままインストールを進められます。

続いてインストール・オプションの選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/98043228-f844-4435-58fe-8715d7d44be3.png)
データベースの作成も同時にできますが、今回はいろいろ操作してみることが目的なので、ソフトウェアのインストールのみにします。

データベース・インストール・オプションの選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/9130c538-fdf4-8e2f-a188-02b57ade87bd.png)
ここは単一インスタンス・データベースのインストール。

データベース・エディションの選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/8bb81f73-5322-5ac0-fa9c-9e0783e5fe33.png)
せっかくなのでEnterprise Editionを選択

ホーム・ユーザーの指定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/d404df65-a302-997a-cf6b-b4e19e62056f.png)
ここは仮想アカウントの使用を選択

インストール場所の指定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/e1f869cf-dc4c-939b-8bdb-52c2efc8915f.png)
ここは任意のフォルダにしましょう。

インストール構成と環境が要件を満たしてるかチェックしてくれます（やさＣ）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/538c9bb1-734e-9c8c-be49-3ffc413c3144.png)

インストール構成のサマリー（概要）がこちら
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/9ff4442e-9f05-66a2-2eca-4b4da727a13f.png)

そいでもってインストール開始
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/d575da2e-d77d-7c0d-a0e8-03708f8e4650.png)

インストール完了！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/372367/0fad6af7-250a-29b5-110f-fd9d34dab2ca.png)
とりあえず今回はここまで。
次はsqlplusを使っていろいろいじりたいと思います。
Railsチュートリアル　第５章

#＜Railsチュートリアル　メモ＞

気づいたことや覚えておきたいことをメモとして残します。


#・HTMLに追加した構文

```<!--[if lt IE 9]>
  <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
  </script>
<![endif]-->```

一部のブラウザ (特に旧式のInternet Explorer) ではHTML5のサポートが不完全である場合がある。
回避するために、
JavaScriptのコード (通称: HTML5 shim (or shiv))3を使ってこの問題を解決！


#・躓いた点：①
以下の画像のように書き換えたところ、```rails s```で起動させても反映されずエラーとなる。
エラーの文言をみたところ、
```<title><%= full_title(yield(:title)) %></title>```
大体この辺りがおかしいよ！と出てきます。
![スクリーンショット 2019-03-31 16.03.45.png](https://qiita-image-store.s3.amazonaws.com/0/378334/3864c1f2-3ee7-3918-a8c5-b46031dbffbc.png)

おそらくfull titleが定義されていないということなのだと思うけど、
定義してたのでは・・・？と頭に？がいっぱい浮かび、ひたすらググる。

色々調べてたら、
テスト用コードのところでのみ定義していたことが判明！

full_title を app/helper/ 下のファイルで定義して、 
erb ファイル中で参照できるようになり解決しました。

```def full_title(page_title) 
  base_title = "Ruby on Rails Tutorial Sample App" 
  if page_title.empty? 
    base_title 
  else 
    "#{base_title} | #{page_title}" 
  end 
end```
rpmのパッケージビルド時にJarファイルを再圧縮しない

RPMビルド時にデフォルトであれば、以下のようにJarファイルを一度展開して再度圧縮します。

```bash
$ rpmbuild --define "debug_package %{nil}" -ba kusakari.spec 
・・・
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
ファイルの処理中: kusakari-1.0-1.el7.centos.x86_64
・・・
+ exit 0
```

標準であれば、JarファイルはGradleなどでリポリトリから取得するべきですが
リポジトリが利用できない環境（セキュリティ区画でのファイル配置など）を想定しています。

**サンプルファイル**

```bash
ls -l /home/kusakari/work/kusakari/
-rw-rw-r-- 1 kusakari kusakari      16  3月 31 21:06 date.sh
-rw-r--r-- 1 kusakari kusakari 4756746  3月 31 21:06 deploy.jar
-rw-rw-r-- 1 kusakari kusakari      23  3月 31 21:06 test.sh
# jdkのjarファイルをサンプルとして使ってます
```

**specファイル**

```bash:kusakari.spec 
Name:	kusakari
Version:	1.0
Release:	1%{?dist}
Summary:	test
Group:	group	
License:	GPLv3+
URL:		https://www.yahoo.co.jp/
Source0:	kusakari.tar.gz

%define __jar_repack %{nil} 
%description
%prep
%setup -n %{name}
%install
rm -rf %{buildroot} 
mkdir -p %{buildroot}/home/kusakari/target/
install -m 0755 test.sh %{buildroot}/home/kusakari/target/
install -m 0755 date.sh %{buildroot}/home/kusakari/target/
install -m 0755 deploy.jar %{buildroot}/home/kusakari/target/

%clean
rm -rf %{buildroot}

%files
/home/kusakari/target/test.sh
/home/kusakari/target/date.sh
/home/kusakari/target/deploy.jar

%doc
%changelog
```

**ビルド**
Jarのrepackがなくなりました。それに伴いビルドの時間も短くなりました。

```
$ rpmbuild --define "debug_package %{nil}" -ba kusakari.spec
+ /usr/lib/rpm/redhat/brp-python-hardlink
ファイルの処理中: kusakari-1.0-1.el7.centos.x86_64
・・・
+ exit 0
```

ビルド時間を短くでき、本オプションを入れておくべきだと思います。
AWS EC2/GCP Compute Engineで構築した環境に、Anaconda環境を構築する。

自分用の備忘メモになります。
AWS EC2/GCP Compute EngineにUbuntuで構築した環境に対して、Pythonによる機械学習をするために、Anacondaをインストールしました。
AWSにはSagemaker、GoogleにはcolabといったPython用の機械学習環境がありますが、一から環境を作れるかどうか試してみました。

１．Anacondaのインストール
２．Anaconda Navigatorの実行

※うまくいかなかったところ
Anacondaインストール後、Anaconda起動しなかった。rootのPATH設定ができていなかったことが原因だった。

１．Anacondaのインストール
こちらの記事から、https://qiita.com/m0p1nt/items/b55b175c78ecfa42eeea
実行してみました。
GUIモードでも、コマンド実行用のターミナルを起動します。
（ターミナル起動のショートカットキー Ctl+ ALT+T）

GUIモードによる接続方法は下記を参照してください。
https://qiita.com/nakajimatakuya0909/items/7658b27436701f099321

Anacondaのインストールは無事に終わったのですが、“conda”コマンドがエラーとなりました。
そこで、こちらの記事からhttp://kaerupyokopyoko.hatenablog.com/entry/2017/10/28/013923
でPATHの設定を行った。これで“conda”コマンドとpython3.7が動作するようになりました。

２．Anaconda Navigatorの実行
引き続きターミナル画面から、“anaconda-navigator”とコマンド入力をすると、anaconda navigatorが起動します。anaconda navigatorからJupyter Notebookが起動できます。

個人的には、ネット接続できる環境があれば、いつでもどこでも機械学習ができるようになれたなと喜んでいます（笑）。
差分ソートアルゴリズム「焔式」の紹介（ベンチマークあり）

# 焔式
焔式（ほむらしき）は、マージソートを応用した、差分ソートです。
ソート済み配列に対し、値の変更を行った箇所に焦点を当て、高速にソートします。

以下の特徴があります（変更範囲をDとして）。

* 比較ソート
* 安定ソート
* 外部領域：N
* 平均時間：O((D log D) + N)
* 最悪時間：O((D log D) + N)
* 最良時間：O(D)
* 再帰：無し


# リポジトリ
[焔式（ほむらしき） Unlicense](https://github.com/EmuraDaisuke/SortingAlgorithm.HomuraShiki)


# 基本となるアルゴリズム
* ソート済み配列に対して、任意の範囲の値を変更します。
* 変更範囲を、比較安定ソートします。
* 「前方範囲、変更範囲、後方範囲」で三区画マージします。

## 具体的な流れ
~~~
ソート済み配列に対して、任意の範囲の値を変更します
0 2 3 4 5 6 7 9|ソート済み配列
    ↓ ↓ ↓
0 2|8 1 3|6 7 9|
~~~
~~~
変更範囲を、比較安定ソートします
0 2|8 1 3|6 7 9|
    ↓ ↓ ↓
0 2|1 3 8|6 7 9|
~~~
~~~
「前方範囲、変更範囲、後方範囲」で三区画マージします
0 2|1 3 8|6 7 9|

02   前方範囲
138  変更範囲
679  後方範囲

012    前方範囲を消費するまで、変更範囲とマージ（前方Part）
36789  変更範囲の残りと、後方範囲をマージ（後方Part）

01236789  前方Partと後方Partを連結（ソート完了）
~~~


# ビルド＆テスト
検証を行った環境は以下のとおりです。

* Windows 10 Pro 64bit
* Core i7-8700 3.20GHz

[颯式](https://github.com/EmuraDaisuke/SortingAlgorithm.HayateShiki)と[刹那式](https://github.com/EmuraDaisuke/SortingAlgorithm.SetsunaShiki)が兄弟ディレクトリに存在する状態でビルドできます。

## **Msvc**
Microsoft(R) C/C++ Optimizing Compiler Version 19.16.27027.1 for x64

~~~sh
cl Main.cpp -Ox -EHsc -Fe:TestMsvc.exe
TestMsvc.exe
~~~

## **clang++**
clang version 8.0.0 (tags/RELEASE_800/final)
Target: x86_64-w64-windows-gnu

~~~sh
clang++ Main.cpp -O3 -o TestClang++.exe
TestClang++.exe
~~~

## **g++**
gcc version 8.3.0 (Rev2, Built by MSYS2 project)
Target: x86_64-w64-mingw32

~~~sh
g++ Main.cpp -O3 -o TestG++.exe
TestG++.exe
~~~


# 平均ベンチマーク
以下は、ソート済み配列に対し、ランダムな範囲を、ランダムな値に変更した場合です。
単位は秒で、数値が低いほど高速です。

## **Msvc**
|件数|std::sort|std::stable_sort|焔式|
|---:|---:|---:|---:|
|10,000|0.00031643|0.00016890|**0.00014270**|
|1,000,000|0.05004999|0.02833382|**0.02414271**|
|100,000,000|3.43509980|3.48550165|**2.55574413**|

## **clang++**
|件数|std::sort|std::stable_sort|焔式|
|---:|---:|---:|---:|
|10,000|0.00027717|0.00020017|**0.00015642**|
|1,000,000|0.03866672|0.02881882|**0.02255046**|
|100,000,000|3.38201222|3.64178056|**2.60998679**|

## **g++**
|件数|std::sort|std::stable_sort|焔式|
|---:|---:|---:|---:|
|10,000|0.00029155|0.00020019|**0.00014887**|
|1,000,000|0.04052708|0.02760306|**0.02054782**|
|100,000,000|3.58270940|3.45231729|**2.36870185**|


# 特性ベンチマーク
以下は全て、「100,000,000」件でソートしました。
単位は秒で、数値が低いほど高速です。

## 最良ケース
ソート済み配列に対し、値を変更せずに、範囲をランダムにした場合です。

||std::sort|std::stable_sort|焔式|
|---:|---:|---:|---:|
|Msvc|0.23993706|1.30073792|**0.01059685**|
|clang++|1.04052412|1.52173567|**0.01611595**|
|g++|1.34400042|1.31273356|**0.01510180**|


# 余談
如何だったでしょうか？

ソートは、常に全体で行う必要はないという観点から、差分ソートという考えに至ったアイデアです。
本来であれば、全体ソートである std::sort と std::stable_sort との比較はフェアではないのですが、差分ソートの有用性を判断していただくには必要かと思い、ベンチマークを掲載することにしました。
参考になれば幸いです。

工夫をすれば、より高速にソートできることが示せたと思います。
運用の目安としては、(D ＜ (N/2))の場合は差分ソート、そうでなければ全体ソートが良いかなという所感です。

ソートアルゴリズムには、まだ浪漫が残っています。

---
以下の記事も併せて読んでいただけると、より楽しめるかも知れません。
* [「高速な比較安定ソートアルゴリズム「颯式」の紹介」](https://qiita.com/EmuraDaisuke/items/fbcfbdae8e0477693331)
* [「新手法の提案：差分ソートアルゴリズム「刹那式」の紹介（ベンチマークあり）」](https://qiita.com/EmuraDaisuke/items/292097634e73d43f353a)
Django簡単なアプリケーションができるまで⑤

#おさらい
前回は管理者ページにログインしpostを追加するまでをやりました。

#追加したpostの内容をわかりやすく
今記事では追加したpostの内容をブラウザに表示したいと思います。
ですがその前にpost一覧画面のPost object(1)となっているところを
<img width="1147" alt="スクリーンショット 2019-03-30 10.15.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/376889/e3cc5713-e0ff-4694-41a7-9fa41a4a4944.png">
わかりやすい様に投稿したpostの題名が帰ってくる様に編集します。

```Python:/アプリケーションフォルダ/models.py
def __str__(self):
    return self.title
```
__str__という関数を定義し、返り値としてクラスのtitleを指定しています。
<img width="1143" alt="スクリーンショット 2019-03-30 10.43.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/376889/40518630-4772-cc74-7af2-bdb3cbbdc368.png">
http://127.0.0.1:8000/admin ブラウザを更新してpost管理ページに飛ぶと以上の様にタイトルが表示されています。

これで自分が追加したpostの内容がわかりやすくなりました。

#templatesフォルダの追加
ブラウザに表示させますので、HTMLファイルが必要になってきます。
アプリケーションフォルダの中にtemplatesフォルダを追加し、その中にアプリケーション名と同じフォルダを追加し、その中にindex.htmlファイルを作成します。

```
・プロジェクトフォルダ
    ・
    ・
    ・
    ・アプリケーションフォルダ
        ・templates
            ・アプリケーションと同じ名前のフォルダ
                ・index.html
        ・
        ・
        ・
```


#ブラウザに表示
いよいよブラウザに表示していきたいと思います。

```Python:/アプリケーションフォルダ/views.py
from .models import Post

def index(self):
    posts = Post.objects.order_by('-published')
    return render(request, 'posts/index.html', {'post': posts})
```
modelsの中からPost classをインポートし、
前回までに定義していたindex関数の中身を以上の様に書き換えます。

変数postsの中には、降順でソートしたオブジェクトを代入し、返り値としてposts/index.htmlにキーpostで中身をpostsで指定します。
この様に書くことでindex.htmlが呼び出された時にindex.htmlで扱っているpostsに入っている値を使うことができる様になります。

肝心のindex.htmlを編集していきます。

```HTML:index.html
<!DOCTYPE html>
<html lang="ja-jp">
<head>
    <meta charset="UTF-8">
    <title>posts detail</title>
</head>
<body>
<h1>Welcome to my page.</h1>

<h2>NEW POSTS.</h2>

{% for post in post.all %}
    {{ post.title }}
{% endfor %}

</body>
</html>
```
肝心なコードはbody句にあります。{% ... %}この様な書き方は[Jinja2](http://jinja.pocoo.org/docs/2.10/)というテンプレートエンジンによる記法です。Djangoにはこのテンプレートエンジンを備えています。

オリジナルの記法を用いてPythonから渡されたオブジェクトや条件分岐、ループといった処理を簡単に行えます。

ここまで書けたら http://127.0.0.1:8000/posts を見に行ってみましょう
<img width="1089" alt="スクリーンショット 2019-03-31 21.01.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/376889/cb0910b7-85c4-4867-1538-04adc8db8841.png">
この様に管理者ページで追加したpostの題名やhtmlファイルで記述している題名等がブラウザで確認できるかと思います。


この記事はここまで
GitHubに草が生えなかったが、解決した話

同様の記事はたくさんありますが、自分と全く同じ状況のものはなさそうですので、記録しておきます。

# その現象は、突然に
GitHubのプライベートリポジトリが無料で作れるようになって以来、いくつかのリポジトリを作成してコミットを重ねてきました。

そして、いわゆる「草」が生える様子も励みにしていたのですが...

ある日ふと気がつくと、草が生えていません。
Contribution activity も増えていません。
何度も git push しているのに。

- 自分で独自に作ったリポジトリ（forkではない）
- メールアドレスの設定はローカルとサーバで一致している（GitHubオススメの「noreply」アドレスを使用）

間違いはなさそうだが...

:thinking:

念のため、各リポジトリのcommitsも確認してみる。

・
・
・

！？

「Last commit」の欄に**全く知らないユーザのアイコンと名前が**。:worried:
誰だお前！？:angry:

※動転してキャプチャ撮り忘れ。下記キャプチャは正常化後のものです。
　ここが自分ではないユーザになっていました。
<img width="985" alt="スクリーンショット 2019-03-31 17.52.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/120785/2cbfaa50-c5fc-d6c6-acb3-d53d517bb85c.png">

とりあえずそのユーザは、Settings - Blocked users に突っ込む。

そうしたら、とりあえず知らないユーザは消え去って自分のコミットに戻った。
しかし、アイコンが表示されない。
<img width="157" alt="スクリーンショット 2019-03-31 17.58.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/120785/d359818d-feec-c133-b7d7-5a75817c9ea2.png">
なんだかまだ不穏な感じだが、一旦作業に戻る。

# それでもやっぱり草が生えない
その後 git push を何度か実施。
Last commit は自分のユーザ名で表示されるが、アイコンはグレーのオクトキャットのまま。
そして、草は相変わらず生えない。

試しにOSSのリポジトリをforkしてみたら、それはcontributionと見なされて、草も生えた。
自分で新たにプライベートリポジトリを作成したら、それも草が生えた。
でも、既存のリポジトリにpushしても、草は生えない。

なぜだ...
これではこの後いろいろと開発を進めても、全く草が生えてくれないではないか...

:thinking:

# メールアドレスを変えてみた
様々なサイトを検索するも、contributionに関してはメールアドレスを見直せという情報しか出てこない。
そこで、GitHubオススメの「noreply」アドレスを使うのをやめ、自分で用意した別のアドレスに変えてみることに。

管理画面側で、Setting - Emails から Add email address を実施。
さらに、Setting - Profile から Public email を追加したものに変更。
そして、ローカル側でもそのアドレスを設定。（下記アドレスはサンプルです）

```sh
$ git config user.email new_address_for_github@example.com
```

これで既存リポジトリにpushしてみると...

:grinning:

治った！
<img width="985" alt="スクリーンショット 2019-03-31 17.52.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/120785/a711a0f3-1d89-0343-448f-323ac30d4139.png">

アイコンも本来のものに戻った。

※ただし、おかしくなっていた時期にコミットした分はグレーのオクトキャットのまま。
<img width="168" alt="スクリーンショット 2019-03-31 20.48.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/120785/57074ae0-6e74-5ee6-d84a-46572d3dc888.png">

草も生えた！
<img width="212" alt="スクリーンショット 2019-03-31 20.51.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/120785/b04da7e4-5a6c-f2f9-1182-2ff93c20a86d.png">


これで、今後は大丈夫でしょう。

解決！

# ちなみに
Two-factor authentication も有効にしておきました。
今回の件が事故なのか事件なのかはわかりませんが、アカウントを乗っ取られたら嫌ですからね。
これだけは覚えておきたいgitコマンド

毎年、新人や新規参画メンバが入ってくるタイミングで苦労しています。
いっそのこと「これだけ覚えとけ」ってやつをまとめることにしました。

## 前提
* 参画メンバはgitを初めて使う人たち
* GitLab
* ブランチ戦略は[git-flow](https://nvie.com/posts/a-successful-git-branching-model/)を採用
* ブランチ作成はgitlabのissueから`Create merge request`で作成

## コマンド
### リモートリポジトリをローカル（自分のPC）に複製する。

```
git clone {リポジトリURL} 
```

### リモートのブランチをチェックアウト
```
git checkout -b {ローカルブランチ名} origin/{リモートブランチ名}
```

### 作成したファイルを索引（コミット対象）に追加する

```
# ファイルを指定して追加
git add {ファイルパス}
# 一括で追加
git add .
# ワイルドカードも可能
git add *.java
```
## 変更をコミットする。

```
git commit -m コミットメッセージ
```

## ローカルでの変更をリモートリポジトリへ反映する

```
git push
```
僕はこれで０からJS勉強しました　〜Udemy感想その５〜

# 概要
４月(明日から！)からエンジニアとして新社会人になります
内定もらってから1年くらいUdemyでプログラミング学習(主にWeb系)をしていて、
修了した講座も増えてきたので感想を書いてます

今回はその５です
同じように初心者からWeb系の勉強始める人の参考なれば、、、

今日はJavaScriptの講座を紹介します
僕はそれまでJS書いたことなかったんですが
やっぱりJSは動きがあるので勉強してて楽しかったです（感想がしょぼい）

# 使った講座
[Modern JavaScript From The Beginning](https://www.udemy.com/modern-javascript-from-the-beginning/)

英語の講座です、字幕あり
21.5時間で料金は￥21000
（Udemyは頻繁に全講座￥1400セールみたいなの
やってるので絶対その時に買った方がいいです）

# 勉強してる頃の自分
JavaScriptは多分一回も書いたことなかったです
console.logで出力するってのも
この講座で初めてやりました

#良かった点
- **本当に初めての人でも大丈夫！**

自分が全く触ったことない状態からのスタートだったのでこれは自信を持って言い切れます！
本当に初めてでも大丈夫です
JS初心者だった僕は、この講座をやり終えてからボタンを押すとAPIを使ってJSONでデータ取ってきて
ブラウザに表示ってくらいのコードは自分でかけるようになりました

 - **各レクチャーごとにそれまで書いたコードがダウンロードできる**

過去に書いた講座の感想でも言ってたんですが
僕はUdemyでよく書き写しミスをしてその原因の特定に下手をすると数時間費やします

各レクチャーごとにコードが文字起こしされているものはあったのですが
この講座はzipファイルとしてダウンロードできるので
どうしてもわかんなかったらスキップが可能です
(自分に言い聞かす意味も込めてですが最後までできたらぜひスキップしたところをやってみましょう)

#今ひとつだった点
 - **途中で出てくるサービスがAPIの使用が有料になってる**

途中で天気予報のサービスのAPIを使用するレクチャーがあるんですが
この講座ができた時にはおそらく無料だったAPIが有料になってます

Q&Aのところを見れば一応代わりのサービスが乗ってるんですが
有料なの知ってるならできれば動画にちょろっとでも書いといて欲しかった

# まとめ
JSだけで１０個くらいサービスを作るので「こんなに色々できるんだ！」と
勉強していて楽しい講座でした
進むスピードはおそらくゆっくりなので僕のような全く触ったことない人におすすめです
ただ少しはわかるぞって方もファイルダウンロードすれば途中から勉強することもできるのでぜひやってみてください
独学エンジニアが1年半知らなかった、使わなかったlinuxの便利なコマンド 







まずは、historyから。
コマンドの履歴を表示してくれる。

```shell
$ history
```

ログアウトしても以前に実行したコマンド履歴が観れるのだが、それは、「bash_history」という隠しファイルにあるらしい。

```shell
$ cat ~/.bash_history 
```
で確認。


以下の二つが衝撃だった。（恥ずかしながら知らなかった。。。そりゃこんなコマンドあるに決まってるよな。。。）

Ctrl + Aでコマンドの先頭へいき、Ctrl + Kでコマンド一括削除

```shell
$ Ctrl + A
$ Ctrl + K
```

rails g contorller~~~~~~なんて長いコマンドを消すのは大変だったがこれで一発。

こちらは、直前に実行したコマンドを再実行してくれる。

「↑キー」押してエンターとまあ変わらないか。。。。

```shell
$ !!
```

 直前にいたディレクトリに移動するコマンド。頻繁にディレクトリを移動する時とかは便利。

```shell
$ cd ~_
```

以下は、以前に実行したコマンドを検索してくれる。

```shell
$ Ctrl + R
```
を押すと、ターミナル上で

```shell
(reverse-i-search)`': 
```

のように変化するので、ここで好きな文字で検索できる。

linuxの本をちらっと読んでみて知らなくて便利なコマンドが割とあった。
特に、検索系とか一括操作系は考えたら「当然ある」訳で、今後の教訓にもなった。
AMIとは


#AMIとは
・OSの情報やディレクトリ、ファイル、ブロックデバイスマッピングなどインスタンス作成に必要な情報を一通りまとめたもの（インスタンスはAMIのコピー）
・このAMIを元にインスタンスを立てる（AMI作成=>インスタンス作成）

#AMIの作成方法
- インスタンスのスナップショットからも作成可能。
これは、インスタンスのバックアップになる。そして、インスタンスとそれにアタッチされているEBSのデータを1つのAMIにパッケージ化できる。

![スクリーンショット 2019-03-14 1.42.53.png](https://qiita-image-store.s3.amazonaws.com/0/199131/1737c280-6ccb-aa4d-8ca7-1a2806072ff5.png)
Ubuntuで構築したAWS EC2/GCP Compute Engineの環境をGUIモードで実行する。

自分用の備忘メモになります。
AWS EC2やGCP Compute EngineをUbuntu18.04で構築した環境に対して、コマンドモードだけでなく、GUIモードで実行するための準備事項になります。

手順
１．環境構築
２．コマンドモードでGUIインストール
３．リモートデスクトップ（Windows）で環境にアクセス

１．環境構築
AWS EC2やGCP Compute Engineの環境構築は割愛します（すみません）。
AWS EC2で環境構築時にセキュリティグループの設定を行わなかったので、自分のPCからEC2にリモート接続できないと事態を招いたので記述します。

対応：インバウンドに“RDP”の接続を追加する。
対応方法：下記の黄色蛍光ペンの“RDP”行を追加し、ソースを“0.0.0.0/0”とします。こうすることでどのPCからもリモートデスクトップ接続ができるようになります。
なお、世界中からアクセスできるようになるので、個人的な練習用の環境のやり方です。
（本サービスを前提とする場合は別の機会に説明したいと思います。）
![aws.PNG](https://qiita-image-store.s3.amazonaws.com/0/156361/4df0c7b0-622e-a366-7d1f-9136ca8ab17c.png)

GCP Compute Engineでは、環境作成とともにデフォルトでRDPが用意されます。

２．コマンドモードでGUIインストール
AWS EC2/GCP Compute EngineともにSSHからCUIモードで接続します。
その後、こちらの記事から、https://qiita.com/osugizmo/items/21578272ae2db05ab001
GUIインストールをやってみました。
GCP Compute Engineの場合、
“sudo apt install gnome-core”を実施するとエラーとなったので、
“sudo apt update -y”
“sudo apt upgrade -y”
を実施し、
再度“sudo apt install gnome-core”実施し、無事GUIインストールができました。

無料版のメモリのスペックでは、GUIモードはレスポンス・動作とも遅いので、
GCPでは、“n1-standard-4（vCPU x 4、メモリ 15 GB）”にしました。
もちろんAWSでも同様にしました。

３．リモートデスクトップ（Windows）で環境にアクセス
リモートデスクトップ接続するために、IPv4パブリックIP/外部IPアドレスを取得します。
・AWS
![aws リモートデスクトップ接続用.PNG](https://qiita-image-store.s3.amazonaws.com/0/156361/e4d8a475-f7b9-d34c-4409-10fb75a75623.png)

・GCP
![GCP リモートデスクトップ接続用.PNG](https://qiita-image-store.s3.amazonaws.com/0/156361/83671d03-8d57-e513-d1a2-9a5239229419.png)

この後は、AWS EC2/GCP Compute Engineにリモートデスクトップ接続できます。

※AWS EC2でUbuntu16.04LTSのデスクトップ対応についてはAWSの以下のURLに記載していました。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/connect-to-ubuntu-1604-windows/
←こちらリンク切れしていました。
ディスクトップインストール後はこちらを参考にしてください。
https://qiita.com/tmikada/items/be27df3affc56eeffd8b
EBSとインスタンスストアとは

#インスタンスの２つの保存領域

1. インスタンスストア
2. EBS

インスタンスにも確かに記憶領域（インスタンスストア）はあるのだが、こちらは**インスタンスの停止や削除とともに破棄されてしまう**

![スクリーンショット 2019-03-14 1.09.23.png](https://qiita-image-store.s3.amazonaws.com/0/199131/b83da311-20e1-d44c-76db-bb576c2e135b.png)

そこで、データを永続化するために、インスタンスに外付けHDDのような感じで記憶領域を確保できるのがEBSである。

![スクリーンショット 2019-03-14 1.10.36.png](https://qiita-image-store.s3.amazonaws.com/0/199131/1abb4e03-1d95-7595-b7af-2061340d656f.png)
goにおけるchannelの使い方


#mainスレッドとgoroutine間で値を渡すには**channel**を使う

![スクリーンショット 2019-03-12 21.39.01.png](https://qiita-image-store.s3.amazonaws.com/0/199131/0519ddd7-44cc-bf4a-4da6-eafdde31430c.png)

1.make(chan 型)でchannelを作成
2. goroutineにchannelを持たせ、go goroutine(変数, channel)とする
3. 値は、「c <- numで受信、<-cで送信」（cはchannnel）
4. cに値が入るまで、<-cの次の行を実行させないことが可能

```go:main.go
package main

import (
	"fmt"
)

func goroutine(s []string, c chan string) {
    var str string
	for _, v := range s {
		str += v
	}
    //c <- numでnumを受信
    //ここで受信するまで、mainスレッドでは次の行に行かない
	c <- str
}

func main() {
	s := []string{"Hello","World","!","Mr.","Ren" }
    //make(chan string)でstring型のchannelを作成
	c := make(chan string)
    //goroutineに渡す
	go goroutine(s, c)
	//xはsumが入ってくるまでずっと待ってる（ブロッキング）。入ってきたら次の行へ（sync.WaitGroupで待つ必要はない）
    //<-cで受信した値を送信
	x := <-c
	fmt.Println(x)
}

//処理結果
//HelloWorld!Mr.Ren
```
channelを使ったselect




goroutineを使い、その値を受けわたすにはchannelを使う。
ただ、channelが複数あり、それぞれ同時に実行したい場合は、**for~select**を使う。

![スクリーンショット 2019-03-13 18.27.40.png](https://qiita-image-store.s3.amazonaws.com/0/199131/c25c3c0c-8685-dff0-3191-8f4a5d449e47.png)

以下のようにすることで、二つ（n個）のgoroutineを同時に実行でき、channelをそれぞれに渡すことが可能になる。

```go:main.go
	for {
		select {
         //一つめのchannel
		case msg1 := <-c1:
			fmt.Println(msg1)
         //二つめのchannel
		case msg2 := <-c2:
			fmt.Println(msg2)
		}
	}
```

例えば以下のように、channel1とchannel2という文字を出力し続けるコード。

```go:main.go
package main

import (
	"fmt"
	"time"
)

func goroutine1(ch chan string) {
	for {
		ch <- "channel1"
		time.Sleep(1 * time.Second)
	}
}

func goroutine2(ch chan string) {
	for {
		ch <- "channel2"
		time.Sleep(1 * time.Second)
	}
}

func main() {
	//stringのチャネル1つめ
	c1 := make(chan string)
	//stringのチャネル2つめ
	c2 := make(chan string)
	go goroutine1(c1)
	go goroutine2(c2)
	//同時に受信が可能
	for {
		select {
		case msg1 := <-c1:
			fmt.Println(msg1)
		case msg2 := <-c2:
			fmt.Println(msg2)
		}
	}
}

//出力結果
// channel2
// channel1
// channel1
// channel2
// channel2
// channel1
// channel2
// channel1
// channel2
// channel1
//・
//・
//・

```
goroutineの実行と、goroutineにおけるsync.WaitGroupの役割

# goroutineの実行
下記のような
「helloを100 * time.Millisecondごとに5回表示するメソッドsayhelloと、worldを100 * time.Millisecondごとに5回表示するメソッドgoroutine」
があるとする。

```Go:main.go
package main

import (
	"fmt"
    "time"
)

func sayworld(s string) {
	for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func sayhello(s string) {
	for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	sayworld("world")
	sayhello("hello")
}
//出力結果
// world
// world
// world
// world
// world
// hello
// hello
// hello
// hello
// hello
```
これは並行処理ではないため、当然上から順に「sayworldメソッド=>sayhelloメソッド」の順に実行される。
ではGoにおいてこれを並行処理（sayworldメソッドとsayhelloメソッドを同時に実行）するにはどうしたらいいか。

**sayworldメソッドの前にgoをつけるだけでいい。**

```Go:main.go
package main

import (
	"fmt"
    "time"
)

func sayworld(s string) {
	for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func sayhello(s string) {
	for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
    //sayworldを別スレッドでgoroutineとして同時実行
	go sayworld("world")
	sayhello("hello")
}
//出力結果
// world
// hello
// hello
// world
// world
// hello
// hello
// world
// world
// hello

```
このようにGoではメインのスレッドで実行される関数と同時実行したい関数に**goとつける**だけで並行処理ができる。

#sync.WaitGroupの役割

次に以下のようにtime.Sleep(100 * time.Millisecond)をコメントアウトしてみる。

```Go:main.go
package main

import (
	"fmt"
    _ "time"
)

func sayworld(s string) {
	for i := 0; i < 5; i++ {
        // time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func sayhello(s string) {
	for i := 0; i < 5; i++ {
        // time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
    //sayworldを別スレッドで同時実行
	go sayworld("world")
	sayhello("hello")
}
//出力結果
// hello
// hello
// hello
// hello
// hello
```
すると、並行処理されているはずのsayworldメソッドが実行されず、sayhelloしか実行されていない。
これは、**mainスレッドのsayhelloが、「sayworldがgoroutineとして起動=>実行」される前に終了してしまった**からである。

![スクリーンショット 2019-03-12 21.12.00.png](https://qiita-image-store.s3.amazonaws.com/0/199131/9ff6ee50-79f2-e722-f276-a0c7b9692f3a.png)



つまり、「sayworldがgoroutinとして起動=>実行」されるのを待てば良い。
それには**wg sync.WaitGroup**を使う

1. wg.Add(n)でn個の並行処理が存在することを伝え
2. wg.Wait()で並行処理が終わるまで（wg.Done()で終了を伝える）、処理をやめない


```Go:main.go
package main

import (
	"fmt"
	"sync"
)

//引数にwgのポインタを宣言
func sayworld(s string, wg *sync.WaitGroup) {
    //wg.Done()で処理の終了を伝える(deferで関数の最後に実行する)
	defer wg.Done()
	for i := 0; i < 5; i++ {
		fmt.Println(s)
	}
}

func sayhelllo(s string) {
	for i := 0; i < 5; i++ {
		fmt.Println(s)
	}
}

func main() {
	var wg sync.WaitGroup
	//wg.Add(n)でwgにn個の並列処理があるということを伝える
	wg.Add(1)
    //実行したいgoroutineにwgのアドレスを渡す
	go sayworld("world", &wg)
	sayhelllo("hello")
	//「goroutinの処理がwg.Done()されるまで終了しないで」と言うことをwg.Wait()で伝える
	wg.Wait()
}

//出力結果
// hello
// hello
// hello
// hello
// hello
// world
// world
// world
// world
// world

```
このようにすることで、しっかりとmainスレッドと、goroutinが並行処理される
[matlab] デフォルト引数の設定方法

pythonだとデフォルト引数を簡単に設定できます（[参考](https://note.nkmk.me/python-argument-default/)）が，MATLABには言語的に用意されていないため，自分で書く必要があります。

## narginを使う方法
`nargin`で入力された引数の個数を判定して，デフォルト値を与えます。

```matlab:mySum.m
function ret = mySum(x1, x2, x3)

switch nargin
    case 0
        x1 = 0;
        x2 = 0;
        x3 = 0;
    case 1
        x2 = 0;
        x3 = 0;
    case 2
        x3 = 0;
end

ret = x1 + x2 + x3;
end
```

## existを使う方法
`exist`で引数が定義されているかチェックして，個別にデフォルト値を与えます。

```matlab:mySum2.m
function ret = mySum2(x1, x2, x3)

if ~exist('x1', 'var') x1 = 0; end
if ~exist('x2', 'var') x2 = 0; end
if ~exist('x3', 'var') x3 = 0; end

ret = x1 + x2 + x3;
end

```

## テスト

```matlab:test.m

global x3
x1 = 1;
x2 = 2;
x3 = 3;

ans(1) = mySum(); % 0
ans(2) = mySum(x1); % 1
ans(3) = mySum(x1,x2); % 3
ans(4) = mySum(x1,x2,x3); % 6

ans(5) = mySum2(); % 0
ans(6) = mySum2(x1); % 1
ans(7) = mySum2(x1,x2); % 3
ans(8) = mySum2(x1,x2,x3); % 6

disp(ans)
```

Matlab R2018a で確認。

```matlab:実行結果
>> test
     0     1     3     6     0     1     3     6
```



## コメント

* 昔から`nargin`を使う方法で書いていましたが，matlabはswitch構文で自動的にbreakされるため，上記の例のように多重定義する羽目になり嫌でした。特に引数が増えると，縦に間延びしてバグが出やすくなります。また，if文でnarginの大小比較を行ってデフォルト値を与えることもできますが，可読性が悪くなるのでお勧めしません。
* `exist`を使った場合，global変数関係でバグが出そうだと思ってましたが，上記テストでは問題ありませんでした。これはなぜかというと，matlabは関数内でグローバル変数を使う場合は，関数内でもグローバル宣言が必要な仕様になっているからです([参考](https://jp.mathworks.com/help/matlab/ref/global.html))。これからは`exist`でデフォルト引数を管理しようと思っています。
* しばらく悩んだが，いい説明用の関数が思いつかなかった…。念のため言っておきますが，上記の`mySum.m`はあくまで説明用です。通常は，[varargin](https://jp.mathworks.com/help/matlab/ref/varargin.html)をつかって，任意個数の引数に対応するよう書いてくださいネ。
SIエンジニアがTOEIC225点上げて、海外研修で質問するまで

# 1.英語のできるエンジニアを目指して勉強開始
最新のIT技術をキャッチアップするには「英語」が必須。
英語のニュースサイトをスラスラ読んだり、Youtubeで海外のプレゼンを聞いたり、海外研修で質問できれば、（欲張りですよね。。）エンジニアとしてステップアップできるなと思い２年前からTOEIC対策＋英会話(AEON)に通いました。

結果、TOEICは225点アップ、海外研修では講演内容を大まかに理解して、質問ができるようになりました！

ポイントは「①継続」「②シャドーイング」「③精読」です。

# 2.TOEICスコアの推移とやったこと
| 時期    | できごと |
|:-------|:------------------|
| 2016/11|AEON TOEIC中級クラススタート(6ヶ月)|
| 2016/12|TOEIC 560点(L345,R215)|
| 2017/05|AEON ラウンドアップレッスン TAKE OFFスタート(８ヶ月)|
| 2017/07|TOEIC 635点(L340,R295)|
| 2017/09|TOEIC 710点(L440,R270)|
| 2018/01|業務多忙で勉強中断|
| 2018/07|AEON ラウンドアップレッスン GEAR UPスタート（８ヶ月）|
| 2018/12|海外研修で質問できるように|
| 2019/01|TOEIC 785点(L425,R360）|

# 3.ポイント①継続　〜週１の英会話〜
業務しつつスキルアップするために一番大事なことは「継続」です。私は、Speakingもできるようになりたかったので英会話学校（AEON）に週1回通うことにしました。

レッスン料は８ヶ月でなんと約２０万(TAKE OFF, GEAR UP)と高額ですが、メリットは多かったです。

- 英語への拒絶反応(長文を見ると頭いたい。。)がなくなる
- TOEICのテクニックを一通り吸収できた(part3,4は必ず設問先に読む、part7も同様、などなど)
- 毎週の課題をやるので勉強する習慣がつく
- SpeakingをすることでListeningがかなり上がる！(=自分が話せるものはラクラク聞ける)

# 4.ポイント②シャドーイング　〜問題集を朝にシャドーイング〜

[TOEIC(R)テスト 新形式精選模試 リスニング(CD-ROM1枚つき)   加藤 優](https://www.amazon.co.jp/dp/4789016595/ref=cm_sw_r_tw_dp_U_x_wPiOCbA8GPG2X)
AEONの先生が持っていたこちらの参考書をリピーティングして、慣れてきたらシャドーイングしました。
最初はスピード早いなぁと感じますが、根気よく何度もやるとスラスラ言えるようになり、「スキル上がってるな！」と楽しくなります。
また、AEONで話す内容がTOEICにも出てきて相乗効果がありました。

普段は最低週に２日、試験２週間前は５日、シャドーイングするようにしました。
毎日やって挫折するより、長く継続できるペースですね。

# 5.ポイント③精読　〜単語は精読中に文で覚える〜
[TOEIC(R)テスト 新形式精選模試 リーディング   加藤 優](https://www.amazon.co.jp/dp/4789016609/ref=cm_sw_r_tw_dp_U_x_7ajOCbPTYVJ8C)
精読は、「単語・熟語を文で覚えること」と「TOEICに出る文章になれること」に注力しました。文法や文型は意識していなかったです。

１問ずつじっくり読みわからない単語をマークしていきました。
最初は途中でつまり読むのに時間がかかりますが、繰り返し読むことで単語・熟語が頭に入るので、スラスラ読めるようになります。

いつもReadingセクションは20問残して終了していましたが、だんだん残す問題数が少なくなり、「読むスピードはやくなったなぁ」と実感しました。

# 6.TOEIC785点とって何が変わった？
## 6.1 できるようになったこと
- 海外研修の内容をざっくり理解して質問できるようになった。
研修参加者がすべて日本人で、講演者がゆっくりと話したこともあり、大まかに何を言っているかは理解できました。
講演中に質問を考え、質問するのですが、相手の回答を即理解して次の質問をすることはできなかったです。
まだまだ精進が必要ですね。

- 海外のITイベントで製品の説明を理解して質問できるようになった。

## 6.2 これからしたいこと
- 英語の技術書をスラスラと読めるようになりたい！
[CISSP Practice Questions Exam Cram: CISSP Pract Quest Exam Cram_4(kindle版)](https://www.amazon.co.jp/dp/B01HF7BE78/ref=cm_sw_r_tw_dp_U_x_RJhOCb3CE6D88)
TOEIC対策でビジネスの単語・熟語はわかりますが、技術書の単語・熟語はまだまだです。
今、担当しているセキュリティの用語を押さえるためにセキュリティ資格(CISSP)の問題集を読んでいこうかと思います。（時間かかりそうー）


- Youtubeで海外の最新技術のプレゼンを理解して情報収集したい！
[Black Hat USA 2018 Keynote: Parisa Tabriz]
(https://youtu.be/py2qmGbyhlw)
TOEICのリスニングはきれいな英語でゆっくりなんですよね。海外のITイベントに参加してネイティブのスピードの速さと訛りに驚きました。多聴でいろいろな英語になれる必要ありですね。

- クイックレスポンスができるように
クイックレスポンスのイメージはTOEICのpart2です。
AEONでたまにフリートークをするのですが、先生の最初の質問に即答えるのがなかなか難しい。質問と答えのパターンをストックして会話のスタートをスムーズにしたいですね。
[Perl]日本の消費税と源泉徴収を自動計算するモジュール作った

先ほど[CPAN](https://www.cpan.org/)にリリースしたモジュールを紹介します。
このモジュールは日本における消費税と源泉徴収のややこしい計算を自動化します。

[Business::Tax::Withholding::JP](https://github.com/worthmine/Business-Tax-Withholding-JP)(Github)
[Business::Tax::Withholding::JP](https://metacpan.org/release/Business-Tax-Withholding-JP)(metacpan)

## 経緯

自前で作っているWebサービス（αテスト中のためリンク貼りません）で、フリーランスの方（最初はライターさん）のために**請求・受注の自動化**を目指しており、請求書のテンプレートを作成していたところ、表題のような計算が必要になりました。

通常、[源泉徴収](https://www.nta.go.jp/taxes/shiraberu/taxanswer/gensen/2792.htm)は100万円以下10％、それ以上は約20％[^1]なのですが、[特別復興所得税なるものが震災のために課税](https://www.nta.go.jp/publication/pamph/shotoku/fukko_tokubetsu/index.htm)されており、**一定期間2.1%増税された**状態であることがわかりました。

[^1]: 正確には100万円以下を10％で計算した上で超過分を20％で計算する

でもロジックは単純でした。100万円を越えるかどうかを判定し、増税期間を自動で検知する機構があれば十分自動計算可能なように思いました。

## 実装

で、どうしようかな、って思ってたらできちゃいました。おおよそ6時間です。[Moose](https://metacpan.org/pod/Moose)ってクソ便利ですね。

```perl
use Business::Tax::Withholding::JP;
my $tax = Business::Tax::Withholding::JP->new();
$tax->price(10000);    # 10000 を代入
$tax->net();           # 非課税額は　10000
$tax->tax();           # 税額は　800
$tax->full();          # 総額は　10800
$tax->withholding();   # 源泉徴収額は　1021
$tax->total();         # 源泉徴収済み税込み金額は　9779
```

こんだけです。

## 更新(2019/04/01)

使ってみたら、源泉徴収をする・しないの選択肢がある場合に色々条件つけるのが面倒臭かった。最初から源泉徴収など無視した計算がしたくなったので[更新した](https://metacpan.org/pod/release/WORTHMINE/Business-Tax-Withholding-JP-0.02/lib/Business/Tax/Withholding/JP.pm)

```perl
$tax = Business::Tax::Withholding::JP->new( no_wh => 1 );
$tax->price(10000);
$tax->tax();           # 800
$tax->withholding();   # 0
$tax->total();         # 10800
```

これにより、ただ消費税を加えるだけの時との場合分けが可能になった。

## 更新(2019/04/03)

- `amount()`というプロパティを加えてデフォルトを1に。
- `subtotal()`というアクセサメソッドを加えて小計の取得に対応。

```perl
use Business::Tax::Withholding::JP;
my $calc = Business::Tax::Withholding::JP->new();
$calc->price(10000);    # 価格に10000を代入
$calc->amount(2);       # 数量に2を代入
$calc->subtotal();      # 小計は　20000
$calc->net();           # 非課税単価は　10000
$calc->tax();           # 税額は　1600
$calc->full();          # 税込総額は　21600
$calc->withholding();   # 源泉徴収額は　2042
$calc->total();         # 源泉徴収済み税込支払い額は　19558
```

より[経理っぽくなりました](https://metacpan.org/pod/release/WORTHMINE/Business-Tax-Withholding-JP-0.04/lib/Business/Tax/Withholding/JP.pm)。

## 最後に

経理の方々の中にPerl使いがどれだけいるかわかりませんが、Perlならそれ自動化できますよ[^2]ってことでEnjoy!

[^2]: javascriptで自動計算を謳うフォームはいくつか確認できるが、モジュールという概念で配布されているものは執筆時点で発見できなかった。
ABC - 073- A&B&C

#AtCoder ABC 073 A&B&C
[AtCoder - 073](https://atcoder.jp/contests/abc073)

**2019/05/27**
　問題名修正
　B問題のコードの書き方を修正 ``int[][]の生成部分``

#A - September 9

 - $mod10$の結果が9かどうか？

```java
	private void solveA() {
		int numN = nextInt();

		while (numN != 0) {
			int wk = numN % 10;
			if (wk == 9) {
				out.println("Yes");
				return;
			}
			numN /= 10;
		}

		out.println("No");
	}
```

#B - Theater

 - 同じ席に複数人が座ることはないため、団体の占有している席の総数を調べる

```java
	/*
	 * Streamですべてを組み立てたみた
	 */
	private void solveB() {
		int numN = nextInt();

		int[][] wk = Stream.generate(() -> new int[] { nextInt(), nextInt() }).limit(numN).toArray(int[][]::new);
		//		int[][] wk = IntStream.range(0, numN).collect(() -> new int[numN][2], (t, i) -> {
		//			t[i][0] = nextInt();
		//			t[i][1] = nextInt();
		//		}, (t, u) -> {
		//			Stream.concat(Arrays.stream(t), Arrays.stream(u)).toArray(int[][]::new);
		//		});

		int res = Arrays.stream(wk).mapToInt(i -> (i[1] - i[0]) + 1).sum();

		out.println(res);
	}
```

#C - Write and Erase

###setを使った解法

 - すでに取得していた数値ならremoveする
 - まだsetに格納していない数値ならaddする

```java
	private void solveC2() {
		int numN = nextInt();
		long[] wk = LongStream.range(0, numN).map(i -> nextLong()).toArray();

		Set<Long> wkSet = new HashSet<Long>();
		for (long l : wk) {
			if (wkSet.contains(l)) {
				wkSet.remove(l);
			} else {
				wkSet.add(l);
			}
		}

		out.println(wkSet.size());
	}
```

###最初に入力を配列にしないで直接処理にまわしてみた。こっちのほうが100ms以上速い。

```java
	private void solveC() {
		int numN = nextInt();

		Set<Long> wkSet = new HashSet<Long>();
		for (int i = 0; i < numN; i++) {
			long key = nextLong();
			if (wkSet.contains(key)) {
				wkSet.remove(key);
			} else {
				wkSet.add(key);
			}
		}

		out.println(wkSet.size());
	}
```
【IBM Watson】気象観測データを元に平均気温を予測する - scikit-learn

#はじめに
- IBM Watson上で[CSVを読み込んだ](https://qiita.com/yut-nagase/items/4c9a6334a617184bc9b7)あと[Pandasでデータ操作](https://qiita.com/yut-nagase/items/818f9f87675471d383af)した記事の続きです。
- 今回は、DLした気象観測データを機械学習させて、平均気温を予測させてみます。
- が、実際に行う事は、可読性も加味し、過去の気象観測データのうち「最低気温」と「最高気温」、「平均気温」のみを扱っています。

# 気象庁のサイトから学習データをDLしてCSVファイルを編集
- [ここ](http://www.data.jma.go.jp/gmd/risk/obsdl/index.php)から、任意の地点、任意の期間の気象データをDLしてください。
- 項目として「日最高気温」、「日最低気温」、「日平均気温」はCSVに含めてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235774/c3d4e872-28e4-1403-1a61-0fb683b2ad93.png)

- 地点、項目、期間などを選択したら、「CSVファイルをダウンロード」ボタンをクリックしてください。
- DLしたCSVファイルを任意のエディタで開いてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235774/9f39578b-44b6-448b-0d2d-2c69cca848bd.png)

- ヘッダに無駄な行が含まれているので、削除。かつ、カラムが日本語となっているので、任意の英数の名称に変換してください。エンコードもUTF-8に修正してください。
- ちなみに私は以下のように修正しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235774/094ee5be-d3af-03dd-f1b4-195e1c84b719.png)

- 今回使用するカラムは以下を想定しています。
    - 最高気温(℃) →　max_templ
    - 最低気温(℃) →　min_templ
    - 平均気温(℃) →　avg_templ

#機械学習側の話

##CSVファイルの読み込み
- [この記事](https://qiita.com/yut-nagase/items/4c9a6334a617184bc9b7)を参考にして、上記で準備したCSVファイルを読み込んでください。

##Notebookで学習のコードを記載
- 上記までの手順で、既に、自動生成されたコードが以下のように存在しているはずです。


```py
import types
import pandas as pd
from botocore.client import Config
import ibm_boto3

def __iter__(self): return 0

(中略)

df_data_1 = pd.read_csv(body)
df_data_1.head()
```

- その後のCellに以下記載。必要なカラムだけ配列に格納し、Data Frameに読み込みます。

```py
columns = ['max_templ','min_templ','avg_templ']
data = df_data_1[columns]
data.head()
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235774/9dc3438b-9fad-3bb3-0fa1-8a0864cec6b5.png)

- CSVファイルから読み込んだデータを8:2で訓練データとテストデータに分割し、線形回帰で学習まで行います。
- コメントにも記載していますが、test_size=0.2で20%をテストデータ指定しています。

```py
# 説明変数Xの準備
X_var = data.drop('avg_templ', axis=1)
X_array = X_var.as_matrix() 

# 目的変数Yの準備
y_var = data['avg_templ']
y_array = y_var.as_matrix() 

# scikit-learnの準備
from sklearn.model_selection import train_test_split
# 訓練データとテストデータに8:2で分割
X_train, X_test, y_train, y_test = train_test_split(X_array, y_array, test_size=0.2, random_state=0)

# 線形回帰で学習
from sklearn import linear_model
model = linear_model.LinearRegression()
model.fit(X_train, y_train)
```

- 学習モデルを評価します。訓練データ、テストデータともに、99%以上の精度です。

```py
# 訓練データを用いた評価
print(model.score(X_train, y_train))
# テストデータを用いた評価
print(model.score(X_test, y_test))

出力結果=>
0.99661996229
0.996522453685
```

- 実際に予測してみます。まず、テストデータ配列1件目で予測

```py
pd.DataFrame([X_test[0]], columns=columns[:-1])
print([X_test[0]])
model.predict([X_test[0]])

出力結果=>
[array([ 24.4,  18.1])]
array([ 20.83377488])
```

- 最高気温：24.4、最低気温：18.1の日の平均気温が20.83377488と予測しています。実際に当日の気温を確認すると、以下のように21度となっていますので、良い精度です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235774/353224ec-6b09-37e7-eadd-c75fe3a9bdc7.png)

- 上記だけだと、分かりづらいので、最高気温30度、最低気温10度で平均気温を予測させて見ましょう。

```py
test_arr = [[30,10]]
model.predict(test_arr)

出力結果=>
array([ 19.55658127])
```

- 平均気温19.55658127度なので、妥当な線なのではないでしょうか。

#まとめ
- 今回は分かりやすさを求めたので、最高気温と最低気温から平均気温を求めるシンプルなものでした。もう少し、「日平均雲量」、「日合計全天日射量」といった要素を組み入れて予測したら面白くなると思いますので、ぜひトライしてみてください。
jsdoでdetectDTMF

#概要

jsdoでdetectDTMFやってみた。


#写真

![](http://jsdo-static-contents.s3.amazonaws.com/images/capture/8/y/g/8ygS.jpg?t=1554031533)

#参考にしたページ

https://qiita.com/soramimi_jp/items/4e196dd4f741afb9bb50


#成果物

http://jsdo.it/ohisama1/8ygS

以上。