OmniAICreator/Qiita-1.07M huggingface dataset:
LINE WORKS API 1.0 から 2.0 へのアップグレード

# はじめに
LINE WORKS様より
「LINE WORKS API 2.0」が2022年4月01日に公開されました！！（遅

https://line.worksmobile.com/jp/pr/20220404/

それに伴い
「LINE WORKS API 1.0」は2023年4月30日に提供終了されることに...

https://developers.worksmobile.com/jp/document/10016001?lang=ja

「LINE WORKS API 1.0」で稼動中のBOTやシステムが多々あるので
「LINE WORKS API 2.0」へのアップグレード対応を行う必要がある！

ということで、アップグレード対応を行う際に役に立った記事や
引っ掛かった点をまとめさせていただきます。

※基本的にPythonで実装行っている為、他言語のコードや参考記事は記載しておりません。

# 最初に必ず確認しておくべき記事

## LINE WORKS公式 API 2.0とAPI 1.0の違い
https://developers.worksmobile.com/jp/reference/difference-between-api?lang=ja

変更点がざっくりまとめられています。

## LINE WORKS公式 API 2.0 Botへのアップグレードガイド
https://developers.worksmobile.com/jp/reference/bot-upgrade-guide?lang=ja

「LINE WORKS API 2.0」へのアップグレード手順や、変更点がまとめられています。

1.0からアップグレードを行う場合、プロパティ名の変更に気付きにくい部分がある為
『付録 : プロパティ名変更一覧』は特に確認しておいた方が良いです。

# 必要に応じて確認すると幸せになれる記事
## API 2.0 トークン取得方法 Service Account認証（Python）
https://qiita.com/mmclsntr/items/0c118f40ffe7f36cd4eb

## API 2.0 PostmanでAPI試行
https://qiita.com/mmclsntr/items/eee8d8f3546410fe6652

## API 2.0 オウム返しBOT
https://qiita.com/mmclsntr/items/5ee3b7f2422b05bc256c

Shintaro Yamasaki(@mmclsntr(ワークスモバイルジャパン株式会社) )様の記事が
とてもわかりやすく、参考になりました。
この場を借りて感謝を！！

# アップグレード対応を行う際、引っ掛かった点
## BOTからのメッセージ受信に含まれるパラメータの変更

API 1.0の場合
**「accountId」へ「ユーザのメールアドレス」**
**「roomId」へ「ルームを特定するID」**
が格納されていたが

API 2.0の場合
**「userId」へ「ユーザのID」**
**「channelId」へ「ルームを特定するID」**
が格納されるよう変更されている
※ついでに **「domainId」** も格納されている

### API 1.0 メッセージ(Callback) 受信

https://developers.worksmobile.com/jp/document/100500901?lang=ja
```
{
  "type": "message",
  "source": {
    "accountId": "admin@example.com",
    "roomId": "12345"
  },
  "createdTime": 1470902041851,
  "content": {
    "type": "text",
    "text": "hello"
  }
}
```

### API 2.0 メッセージ(Callback) 受信

https://developers.worksmobile.com/jp/reference/bot-callback-message?lang=ja
```
{
  "type": "message",
  "source": {
    "userId": "c72af563-0f21-4736-11e4-045237113344",
    "channelId": "12345",
    "domainId": 40029600
  },
  "issuedTime": "2022-01-04T05:16:05.716Z",
  "content": {
    "type": "location",
    "address": "〒150-0002 東京都渋谷区渋谷２丁目１５−１",
    "latitude": 35.6587750,
    "longitude": 139.7052230
  }
}
```

API 1.0で実装したBOTの場合
ユーザの特定を **「ユーザのメールアドレス」** で行っているケースが多いので

API 2.0へアップグレードする際、DBなどへの影響を考慮しつつ、必要に応じて
**ユーザーの取得 API** を利用し、**「ユーザのID」** から **「ユーザのメールアドレス」** を取得する必要がある

https://developers.worksmobile.com/jp/reference/user-get?lang=ja

なお、API 2.0 でも API 1.0 と同じく
**「ユーザのメールアドレス」** でメッセージの送信を行うことができる為

設計上問題ないのであれば、**「ユーザのID」** から **「ユーザのメールアドレス」** を取得する必要は無い

# おわりに
API1.0からAPI2.0での変更点が数多くあり、以降期間も1年と短いので
アップグレード対応を行う方々は大変かと思いますが、頑張りましょう！

APIとしては、全体的に整理され、とても使いやすい物になったと感じました！

引き続き対応を行い、引っ掛かった点など更新していく予定です。(2022/06/28)
【TypeScript】インデックスシグネチャのオブジェクトで存在しないキーを指定した時の動作

## 概要
インデックスシグネチャは[こちら](https://zenn.dev/tsuboi/articles/ee43ddc5a2cd941de138)の記事にある通り、型のプロパティを動的に設定する場合に用いるものです。いわゆる連想配列のような使い方をする場合に、用いるものになります。
値を取り出すときはキーを指定するのですが、その際に存在しないキーで取り出そうとしたら、どのような動作をするかのメモ書きをします。

## コード例
例えば以下のコードがあるとします。

```typescript
type SampleType = {
  [key: string]: number;
};

const objectKeyMain = () => {
  const sampleType: SampleType = {
    test1: 1,
    test2: 2,
    test3: 3,
  };
  // 「test1」は存在するので「1」が取得できる
  const sample1 = sampleType["test1"];
  console.log(sample1);
  // 「test4」は存在しないがどうなるか
  const sample4 = sampleType["test4"];
  console.log(sample4);
};

objectKeyMain();
```

valueの型は`number`ですが、これで存在しないキーが指定された`sample4`の値はどうなるか。

## 結果
`undefined`になります。そりゃそうだよねという話なのですが、型は`number`型なのに`undefined`になるのは、少し気持ち悪いですよね。
もし存在しないキーが指定されうる場合は、サバイバルTypeScriptの[インデックス型 (index signature)](https://typescriptbook.jp/reference/values-types-variables/object/index-signature)の解説にある、コンパイラーオプション`noUncheckedIndexedAccess`の有効化も対応案の一つです。このオプションを有効化すると、インデックスシグネチャのオブジェクトから取得した値は、指定した型とundefinedのユニオン型になります。
2022/6/28主にITとかセキュリティの記事

尼崎市USBメモリ紛失、関係者は再々委託先 - BIPROGY「あくまで責任は弊社」
https://www.security-next.com/137630

国家関与の攻撃グループ、早期より「VMware Horizon」「UAG」の「Log4Shell」を標的に
https://www.security-next.com/137616

グループ海外拠点でランサム被害、情報共有に時間要す - トヨタ紡織
https://www.security-next.com/137575

日経BPの医療関係者向けサイトに不正アクセス - ギフトコードの不正読み取りも
https://www.security-next.com/137606

個人PCのセキュリティ機能を補う「Microsoft Defender」- 阿久津良和のWindows Weekly Report(6/26)
https://news.mynavi.jp/article/20220626-windows_report/

「ギフトカード詐欺」被害が増加中　イギリスの大手スーパーが顧客に注意喚起(6/25)
https://sirabee.com/2022/06/25/20162882030/

中国が独占禁止法を初改正　ネット普及に対応、8月施行(6/24)
https://www.nikkei.com/article/DGXZQOGM243220U2A620C2000000/

旧式サイバー防御、穴だらけ　「安全」すぐ時代遅れに(6/26)
https://www.nikkei.com/article/DGXZQOUC1344A0T10C22A6000000/

米CISA、クラウド移行を安全に行うためのガイダンス公開 - ゼロトラスト推進(6/26)
https://news.mynavi.jp/techplus/article/20220626-2377638/

クレートとモジュール――Rustのモジュールシステムを理解する(6/24)
https://atmarkit.itmedia.co.jp/ait/articles/2206/24/news007.html

三菱電機が「電安法」に違反、高くついたノイズ試験の見逃し(6/27)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/06950/

さらばパスワード、ウエディングパークがFIDO採用でログイン失敗をゼロに(6/27)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/06943/

SaaSの利用中に接続が切れる　HTTP/2対応が原因(6/27)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800004/061700053/

インターネットのバックボーンは400Gビット/秒へ(6/27)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800012/061600175/
Seleniumでのスクレイピングにて非同期で受信される要素のテキストを取得する

# 問題点
Webサイトで要素の中身が元々空であり、非同期であとから中身が表示されるものがある。
これにより、待機時間が短いと空を取得してしまう。

# 実行環境
M1 Macbook Air
macOS Monterey 12.4
Python 3.10

# 解決方法
## 取得したいテキストが分かっている場合
**そのテキストが表示されるまで待機する**
```Python
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)

driver.get('https://example.com/index.html')
# ページが読み込まれるまで待機
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_all_elements_located)

# 取得したいテキストが表示されるまで待機する
wait.until(EC.text_to_be_present_in_element((By.XPATH, "取得したい要素のXpath"), "取得したいテキスト"))
# スクレピングする
result = driver.find_element(By.XPATH, "取得したい要素のxpath")

print(result.text)
```

これはかなり良き。

## 取得したいテキストが分からない場合

**refresh()を利用して取得できるまでぶん回す。**

```Python
import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)

driver.get('https://example.com')
# ページが読み込まれるまで待機
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_all_elements_located)

# 取得できるまで繰り返す（一応無限ループはやめとく）
for i in range(50):
    # 待機時間
    time.sleep(5)
    # スクレピングする
    result = driver.find_element(By.XPATH, "取得したい要素のxpath")
    
    # スクレピングしたテキストが取得できていたら抜ける
    if result.text != '':
        break
    # テキストの中身が空だったらページを更新する
    driver.refresh()

print(result.text)
```

ゴリ押し感がすごいｗ
うーん、もっと良い方法ないかなあ
【Next.js】useContextのテスト【Jest】

## useContextのテスト
```_test_/Context.test.tsx
import '@testing-library/jest-dom/extend-expect'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { StateProvider } from '../context/StateProvider'
import ContextA from '../components/ContextA'
import ContextB from '../components/ContextB'
import 'setimmediate'

describe('Global state management (useContext)', () => {
  it('Should change the toggle state globally', () => {
    render(
      <StateProvider>
        <ContextA />
        <ContextB />
      </StateProvider>
    )
    expect(screen.getByTestId('toggle-a').textContent).toBe('false')
    expect(screen.getByTestId('toggle-b').textContent).toBe('false')
    userEvent.click(screen.getByRole('button'))
    expect(screen.getByTestId('toggle-a').textContent).toBe('true')
    expect(screen.getByTestId('toggle-b').textContent).toBe('true')
  })
})

```
Twitter API で特定のユーザーのツイートを取得する(Python, tweepy)

# 概要
tweepyというPythonのライブラリを用いて特定のユーザーのツイートを取得する。

# 目次
- tweepy インストール
- Client クラスの作成
- ユーザーid の取得方法
- ユーザーのツイートの取得

## tweepy インストール
ターミナルで以下のコマンドを実行(anaconda)
```
pip install tweepy
```

## Client クラスの作成
tweepyをインポートして、自身の```API_key```などを入れる。
```Client```クラスのデフォルトの```return_type```は```Response```となっているので、必要に応じて、変更できる。詳しくは[公式ドキュメント](https://docs.tweepy.org/en/stable/client.html)

```
import tweepy

API_key = "API_keyを入れてね"
API_key_Secret = "API key Secretを入れてね"
Access_Token = "Access Tokenを入れてね"
Access_Token_Secret = "Access Token Secretを入れてね"
Bearer_Token = "Bearer Tokenを入れてね"

client = tweepy.Client(
    Bearer_Token, API_key, API_key_Secret, 
    Access_Token, Access_Token_Secret,
    # return_type = dict
)
# default return type == Response
# Responseというクラスで返ってくるから必要な情報の取り方はTweepyドキュメントで確認
# type(...)で型の確認が可能

```

## ユーザーid の取得方法
ユーザーidは、[tweeterid](https://tweeterid.com/)というサイトで、TwitterIDを入れると見ることができる。今回は、例として@ twitter のユーザーidを取得した。

```
# @twitter
# idの取得は https://tweeterid.com/
user_id = 783214
```

## ユーザーのツイートの取得
```UsersTweets```にユーザーのツイートの```Response```クラスを入れる。
```UsersTweets.data```でツイートidとツイート内容が入ったlist形式のjsonファイルが得られる。

```
UsersTweets = client.get_users_tweets(user_id)

#Response クラスの中身は https://docs.tweepy.org/en/stable/response.html#tweepy.Response
for tweet in UsersTweets.data:
    print("===================")
    print("Tweet id:",tweet.id)
    print("Tweet text:", tweet.text)
```

出力結果
```
===================
Tweet id: 1540059169771978754
Tweet text: we would know
```
【Tableau】規定のプロパティとは -デフォルトの集計を変更するTips-

# 今回の解消したい課題
- ドラッグアンドドロップでメジャーの項目(値)を行や列に置く際の初期値が __合計__ になることを変更したい
        - 初期値を変更できることを紹介
# 環境
Tableau Desktop 2022.1.3
データソース：サンプル - スーパーストア
***
【テーマ】：四半期ごとの割引率を可視化し、合計から平均にする
1. まずは四半期ごとの割引率を可視化してみる
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/fce3a346-5268-fffc-4233-7f55609aa557.png)
Tableauではおなじみのサンプル - スーパーストアを利用
当然ながらデフォルトは「売上」を行に持っていくと【合計】として集計される
初期値を合計から希望する集計に変更することができる！

2. 規定のプロパティとは
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/abb4f611-0269-f47f-b08d-5f0c68804fcb.png)
言葉の通り、その項目を置く際にどういった集計にするかをあらかじめ設定することができる
「規定のプロパティ」→「集計」→「平均」を選択
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/e145f32b-7859-cd86-63de-3d8da3cb4d28.png)
今まで置くたびに合計で集計されていたものを __平均__ にすることができた

毎回毎回決まった集計に変更することが面倒だなと思っていた人へのTipsでした
***
あくまで個人的な可視化方法なので参考になれば...
Tableauの操作は奥が深い。
Pythonのインストール[2022/06/28版]

# Pyhonのインストール方法

私自身の備忘録のためにPythonのインストール方法を記載していきます。(2022/06/28 現在3.10.5)

## python公式サイトからダウンロード
- [Python公式サイト](https://www.python.org/downloads/)から`[Download Python x.xx.x]`を選択する。

https://www.python.org/downloads/

- ダウンロードした`python-x.xx.x-amd64.exe`を実行する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726394/ee156183-fccc-d4ac-483b-460efaf52ed8.png)
上記画像のInstall Nowに該当するボタンを押す。
(もし、Pathを通す必要がある場合は[Add Python 3.10 to PATH]にチェックを入れておく。)

- 完了したらCloseを押す。

以上でインストールは完了です。

- 入っているかどうかの確認はコマンドプロンプトから以下の方法で試すことができます。(Pathを通している場合のみ)
```:Console
/> Python --version
Python 3.10.5
```
LINQ で複数項目を対象にしたインナージョインを実現する

二つの集合の重複する部分を検出して、重複個所のファイルを削除するクエリをさっと書きたいと思った。
LINQ でできるだろうと思っていたのだけど、やり方を知らなかったので調べた。

# Join

普通にJoinがあるようだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470/103fa055-46a4-158e-a999-1e4546f39f88.png)

* [Perform Inner Joins](https://docs.microsoft.com/en-us/dotnet/csharp/linq/perform-inner-joins)

ここに書いているが、Query expression だった。普段私は Lambda expression を使うので両方で使ってみよう。変換はこちらの[ブログ](https://csharp.academy/linq-join/)
が参考になりそうだが、残念ながら、複数のキーでのJoinに関しては説明がないので、自分でサンプルを書いてみる。複数のキーのJoinは元の本家のでドキュメントに記述がある。

定義は [Enumerable.Join Method](https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.join?view=net-6.0)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470/12f88a02-5e0a-0f1a-460f-c2db7fa8d056.png)

オーバーロードが２つあるが、この表がわかりやすい。`IEqualityComparer<T>` のありなしの違いのようだ。
基本的な意味合いは

`IEnumerable<TOuter> :` インナージョインを実施する時の対抗のコレクション
`Func<TOuter,TKey> :` アウターのコレクションのうち、Joinを実施したいカラムを指定する。複数のキーの場合、Tuple を使うと便利
`Func<TInner,TKey> :` インナーのコレクションのうち、Joinを実施したいカラムを指定する。複数のキーの場合、Tuple を使うと便利
`Func<TOuter, TInner, TResult> :` Join するコレクションがわたってくるので、結果を生成するファンクションをて定義する。

これだけだ。あと試していないけど、`IEqualityCompare<T>` を使うと、自分のカスタムで、インターとアウターのキーが同値であることを定義できるのだろう。

あと、知らなかったけど、こういうときに、[record](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/records) を使うと、サンプル書くのが楽になるんやなぁ。
Query Expression と Lambda Expression は本質的に同じで、書き方が違うだけなので、定義で理解したほうが楽ですね。

# サンプル

```csharp
void Main()
{	
	List<Employee> employees = new()
	{
	    new(FirstName: "Terry", LastName: "Adams", EmployeeID: 522459),
	    new("Charlotte", "Weiss", 204467),
	    new("Magnus", "Hedland", 866200),
	    new("Vernette", "Price", 437139)
	};

	List<Student> students = new()
	{
	    new(FirstName: "Vernette", LastName: "Price", StudentID: 9562),
	    new("Terry", "Earls", 9870),
	    new("Terry", "Adams", 9913)
	};
	
    // Query expression
	var query =
    from employee in employees
    join student in students on new
    {
        employee.FirstName,
        employee.LastName
    } equals new
    {
        student.FirstName,
        student.LastName
    }
    select employee.FirstName + " " + employee.LastName;

	Console.WriteLine("The following people are both employees and students:");
	foreach (string name in query) {
	   Console.WriteLine(name);
	}
	
	// Lambda expression
	var lambda = employees.Join(students, 
                    employee => new {employee.FirstName, employee.LastName}, 
                    student => new {student.FirstName, student.LastName}, 
                    (employee, student) => $"{employee.FirstName} {employee.LastName}");
	foreach (string name in lambda) {
	   Console.WriteLine(name);
	}
	
}


	public record Student(string FirstName, string LastName, int StudentID);
	public record Employee(string FirstName, string LastName, int EmployeeID);
```

```:結果
The following people are both employees and students:
Terry Adams
Vernette Price
Terry Adams
Vernette Price
```
【Ruby】意外と知らない！？標準入力から値を受け取る方法

## 標準入力？
### 標準入力とは
標準入力はプログラムに値を渡す入力元のこと、標準出力はプログラムから出力される値の出力先のことをいいます。 標準入力の仕組みを使うと、キーボードやファイルなど外部から値（データ）をプログラムに与えることができる。

### 前提条件
前提として使用言語は、Rubyになることを予めお伝えしておきます。
そしてPaizaにて標準入力があったため、メモを含めて記事にします。

## １行に１要素だけの場合
```
//標準入力
Tokyo

line = gets
p line

//出力結果
"Tokyo"
```

## １行に複数要素があった場合
```
//標準入力
Tokyo Osaka Kyoto

line = gets.split(' ')
p line

//出力結果
["Tokyo", "Osaka", "Kyoto"]
```

※splitはsplit('')のシングルクォート内の文字で文字列を分解する。
例えば、Tokyoという文字をそれぞれ一文字ずつ取得したければ、シングルクォートの中に何も入れずにすると下記のように取得できる。
```
標準入力
Tokyo
line = gets.split('')
p line

出力結果
["T", "o", "k", "y", "o"]
```
## 複数行に1要素があった場合
```
//標準入力
Tokyo
Osaka
Kyoto

line = readlines
len = line.length
i = 0

while i < len
    line[i] = line[i].chomp
    i += 1
end

p line 

//出力結果
["Tokyo", "Osaka", "Kyoto"]
```

## 複数行に複数要素があった場合
```
//標準入力
Tokyo Osaka Kyoto
Japan USA China
line = readlines
len = line.length
i = 0

while i < len
    line[i] = line[i].chomp.split(' ')
    i += 1
end

p line

//出力結果
[["Tokyo", "Osaka", "Kyoto"], ["Japan", "USA", "China"]]

こういった入力の仕方があることを理解した。
こういった情報を逐一発信していきますので、よろしくお願い致します。
KNIMEでSMILESから分子の三次元構造を作ってみる

## 概要
- KNIMEを用いてSMILESから分子の三次元構造を立ち上げるごく簡単なワークフローを作ってみた。
![スクリーンショット 2022-06-27 22.57.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421491/b2314e85-b58f-0ce5-acc5-d04f43f190b0.png)

- アウトプットイメージ
SMILES：　CC(N)=O 
　↓
三次元構造：
![スクリーンショット 2022-06-27 22.54.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421491/e21cc247-bf62-867b-648e-25bed9c4bf72.png)


## 目的
分子構造のデータはSMILESで入手することが多いが、それは文字列のデータであり、そのままでは量子化学計算等にかけることができない。そこで三次元の構造に変換したい。
いくつかやり方はあるが、KNIMEというツールを使うとサクッとできるらしいのでやってみる。

## 使用したもの
- KNIME 4.5.0
　(https://www.knime.com)
- KNIMEノード
　・RDKitノード
　・Chemistryノード

- データ：T.J.Houらの論文にある1290の化合物のSMILES, 水溶解度、構造記述子がまとまったcsv
（[明治大・金子先生のサイト](https://datachemeng.com/pythonassignment/)で紹介されているもの）
T. J. Hou, K. Xia, W. Zhang and X. J. Xu, ADME Evaluation in Drug Discovery. 4. Prediction of Aqueous Solubility Based on Atom Contribution Approach, J. Chem. Inf. Comput. Sci., 44(1), 266–275, 2004.

## ワークフロー
ざっくりとワークフローでやっていることを解説

### Node1: CSV Reader
csvファイルを指定して読み込む。

### Node2: Molecule Type Cast
選択した文字列を分子の型として変換する。
ここではSMILESとして認識するようにする。

### Node3: RDKit From Molecule
SMILESからRDKitのMol形式に変換する。

### Node4: RDKit Add Hs
分子構造で省略されているH原子を明示的に付加する。

### Node5: RDKit Generate Coords
Mol形式の分子情報を三次元の構造に変換する。
（恐らくDistance Geometry(DG)法を用いている？）

### Node6: RDKit Optimize Geometry
Node5で作成した三次元構造に歪みがある可能性があるので、
念のため、分子力場を用いて構造最適化をする。
（DG法で三次元構造を作成する際には芳香環が歪んでしまうことがあるらしい。）

### Node7: SDF Writer
最適化した構造の列をSDFファイルに出力する。
Avogadroなどの分子構造の可視化ソフトでアウトプットのsdfファイルを読み込んでみると「概要」で示したような立体構造が生成されていることが確認できる。

## まとめ
KNIMEのRDKitノードを使って簡単にSMILESから三次元の分子構造を作成した。
【Ruby】意外と初心者は知らない？頻出メソッド

## Rubyでの頻出メソッドをまとめてみた
### 入力メソッド
```
//入力値:文字列
input = gets

//入力値：文字列
input = gets.chomp

//入力値：数値 
input = gets.to_i

//入力値：数値
input = gets.chomp.to_i
```

上記は文字列および数字を入力する際のメソッドである。
それぞれ二つずつ書いているが、その違いは**改行があるかないか**の違いである。
**chomp**をつけることによって改行がなくなる。

### 配列メソッド
```
//入力値(数値)を配列に格納　
input = gets.split.map(&:to_i)

//分割して配列に格納
a,b,c = gets.split(" ").map &:to_i

//入力値を順番に格納
a = readlines.map &:to_i
```
gets.split.map(&:to_i)は**スペース区切りで数値が並んでいる入力**ができる。
たまにsplit("")と引数に区切り文字の半角スペースを指定している人を見かけますが、splitは引数を省略すると半角スペースで区切ってくれるので、**結果は変わりません**。


[標準入力とは](https://qiita.com/daichi0412/items/0959239b0dfb74c76e70)
C言語でズンドコ

http://qiita.com/shunsugai@github/items/971a15461de29563bf90

しようと思ったら先駆者の方々がたくさんいらっしゃり、私の稚拙なコードが恥ずかしくなってきました。

きっかけはこの方のツイートです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Javaの講義、試験が「自作関数を作り記述しなさい」って問題だったから<br>「ズン」「ドコ」のいずれかをランダムで出力し続けて「ズン」「ズン」「ズン」「ズン」「ドコ」の配列が出たら「キ・ヨ・シ！」って出力した後終了って関数作ったら満点で単位貰ってた</p>&mdash; てくも (@kumiromilk) <a href="https://twitter.com/kumiromilk/status/707437861881180160?ref_src=twsrc%5Etfw">March 9, 2016</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## コード
特に深く考えず、突貫で作ったらこんなようになりました。

```c:kiyoshi.c
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main (int argc, const char * argv[]){
    int rnd;
    int kiyoshi[5] = {0};
    srand(time(NULL));

    do {
        rnd = rand() % 2 + 1;
        switch (rnd){
            case 1:
                printf("ズン　");
                break;
            case 2:
                printf("ドコ　");
                break;
            default:
                break;
        }

        for(int i = 1; i < 5; i++) {
            kiyoshi[i - 1] = kiyoshi[i];
        }
        kiyoshi[4] = rnd;

        if(kiyoshi[0] == 1 && kiyoshi[1] == 1 && kiyoshi[2] == 1 && kiyoshi[3] == 1 && kiyoshi[4] == 2){
            printf("キ・ヨ・シ！\n");
            break;
        }

    }while(1);
    
    return 0;
}
```
今回はBreakする条件分岐がある無限ループを使用しました。
時刻から乱数(1か2)を計算により取得、その値を元に「ズン　」「ドコ　」のいずれかの出力を繰り返しています。
乱数の履歴は判定に必要な５つ分まで配列に格納し、配列の値の並びが特定の状態になったときのみ「キ・ヨ・シ！」を出力したのち、無限ループから抜けてプログラムが終了します。

## 実行例
```
ズン　ドコ　ズン　ドコ　ズン　ドコ　ドコ　ズン　ズン　ドコ　ズン　ズン　ドコ　ドコ　ズン　ドコ　ドコ　ズン　ズン　ドコ　ズン　ズン　ドコ　ドコ　ドコ　ズン　ズン　ズン　ドコ　ドコ　ズン　ズン　ズン　ズン　ズン　ドコ　キ・ヨ・シ！
```
```
ドコ　ズン　ズン　ズン　ドコ　ドコ　ドコ　ズン　ドコ　ズン　ズン　ズン　ズン　ズン　ドコ　キ・ヨ・シ！
```
```
ドコ　ズン　ドコ　ドコ　ズン　ドコ　ズン　ドコ　ドコ　ドコ　ドコ　ズン　ズン　ドコ　ドコ　ドコ　ドコ　ドコ　ドコ　ズン　ズン　ドコ　ズン　ズン　ズン　ドコ　ズン　ドコ　ズン　ズン　ドコ　ズン　ズン　ドコ　ドコ　ドコ　ドコ　ズン　ズン　ドコ　ズン　ズン　ドコ　ドコ　ドコ　ドコ　ズン　ドコ　ズン　ズン　ドコ　ズン　ドコ　ズン　ドコ　ズン　ドコ　ドコ　ドコ　ドコ　ズン　ドコ　ズン　ズン　ズン　ドコ　ドコ　ズン　ドコ　ドコ　ズン　ズン　ズン　ドコ　ドコ　ズン　ズン　ドコ　ズン　ドコ　ドコ　ドコ　ズン　ズン　ドコ　ドコ　ズン　ドコ　ドコ　ドコ　ドコ　ズン　ドコ　ズン　ドコ　ズン　ズン　ズン　ドコ　ドコ　ズン　ズン　ドコ　ズン　ドコ　ズン　ズン　ズン　ズン　ズン　ズン　ドコ　キ・ヨ・シ！
```

果たしてこの出力でいいのかわかりませんが、一応「ズン　ズン　ズン　ズン　ドコ　キ・ヨ・シ！」となっているので良しとしましょう。

## 備考
実行環境...MacOS Monterey 12.4、Macbook Air(Apple M1、16GB)
コンパイラ...(おそらく)Clang
開発環境...Visual Studio Code 1.66.1
huggingface で用意されているモデルの構造を見たい

例えば
```python
from transformers import BertForSequenceClassification
model = BertForSequenceClassification.from_pretrained('bert-base-japanese-whole-word-masking')
```
のようなことをしていたとして、この`BertForSequenceClassification`のアーキテクチャを見たいとする。

# 手段１：単純
単純に
```python
from transformers import BertForSequenceClassification

model = BertForSequenceClassification.from_pretrained('bert-base-japanese-whole-word-masking')
print(model)
```
とする。

# 手段２：ちょっと複雑だがpretrainedパラメータをダウンロードしなくて済む
`from_pretrained()`を使って重みをダウンロードせずに、アーキテクチャを見たい場合。
```python
from transformers import BertForSequenceClassification, BertConfig

config = BertConfig() # get config 
model = BertForSequenceClassification(config) # get model instance

print(model)
```
このようにmodelを事前学習のものではなく初期化した状態で得るときは引数configが必要となる。configとはconfigurationの略で、モデルのハイパーパラメータの一覧である。

huggingfaceには`何々Config`というクラスが沢山あり、そのなかでそれっぽい名前のもの（今回は`BertConfig`）のインスタンスを渡せばいいと思う。今回私は Bert まで打って入力補完でゴリ押した：
![bertConfig_demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2706245/0af541a6-bd9e-64a2-bb96-0c2b62bf0a21.gif)

# おまけ：入出力テンソルの形が見たい
散々使ってきた`print(model)`だと各層の入出力テンソルのshapeが見れない。それを見たいときは https://github.com/TylerYep/torchinfo を使うといい。
【Tableau】ランクチャートの作り方 -備忘録-

# 今回の解消したい課題
- ランクチャートの可視化方法
        - 利用頻度によっては忘れてしまいそうなので、記事化
        - 各Q毎の売上ランキングを可視化する
# 環境
Tableau Desktop 2022.1.3
データソース：サンプル - スーパーストア
***
【テーマ】：四半期ごとの売上合計をランクチャートで作成して可視化する
1. まずは四半期ごとの売上を可視化してみる
![00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/10eca286-2bb5-6173-cfe4-8a3d9cccf872.png)
Tableauではおなじみのサンプル - スーパーストアを利用
サブカテゴリの凡例が多く売上順をみたくても困難

2. ランクチャートを作成
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/1445cdce-80a9-d06b-2f77-daa0fa35763c.png)
合計(売上)を右クリックし
「簡易表計算」→「ランク」を選択
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/11f39bee-90f0-317f-008c-6d12ffe7630d.png)
するとびっくり、思っていたのと違う可視化がされる
各Q毎に今回はランキングを作って欲しい
(初期値は表(横)でランクを表現されている状態)
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/d573bf8b-acc8-ab2b-a0cd-efea34bb59af.png)
慌てずに、合計(売上)を再度右クリックし
「表計算の編集」をクリック
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/b28e995c-0463-b4f3-88c2-5d05c8a006c0.png)
次を使用して計算： の中の __特定のディメンション__ を選択
「サブカテゴリ」を選択
完成！
のように見えるが
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/c9336966-32a3-d779-b6e1-42c4afecb102.png)
ランクを利用した時の注意点として、Tableauでは __値が小さい__ ものが下に配置される
1位を上にしてあげるのが親切！
そこで __軸__ を修正してあげる必要がある
軸で右クリックして __軸の編集__ を選択する
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/032a30c3-edb1-32d9-e210-8321fa1cf256.png)
「スケール」 __反転__ を選択
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/8ec914a2-898c-65a4-f059-31bdb594ee42.png)
完成！

利用頻度によっては忘れてしまいそうなので記載させていただきました
***
あくまで個人的な可視化方法なので参考になれば...
Tableauの操作は奥が深い。
VBAのエラー・メッセージが意味不明で困ったときはOfficeの言語設定を日本語から英語に切り替えよう

## VBAのエラー・メッセージに困った話

わたしはつい最近仕事のため、ExcelとWordを動かすVisual Basic for Applicationプログラミングを習いはじめました。Javaプログラミングの経験はウン十年、素人ではないつもり。しかしVBAには初心者なのでけっこうまごついています。とくにVBAが表示するエラー・メッセージが理解できなくて困っています。

ある時、こんなエラーダイアログに遭遇しました。

![コンパイルエラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52995/432ba69a-d4d6-2954-0a20-bff0ed75d49c.png)

どんなVBAコードがこのエラーを発生させてたかというと、下記のようなクラスモジュールでした。いわゆる「インターフェイス」というやつです。

![IDocTransformer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52995/6a3f9b75-d761-6825-2484-d67b3ec3aaab.png)

まる一日頭を掻きむしったあげくこのコードにミスがあることがわかりました。どこがどう間違っているのかはたいしたことではない、他人さまに向かって述べるほどのことではない。しかしわたしはこれだけ言いたい。**VBAが出力する日本語のエラー・メッセージは意味不明すぎる**、と。

## 誤訳だった

VBAはこう表示しました。

>コンパイル　エラー:
>オブジェクトモジュールにはインターフェイス 'Transform' 用の 'IDocTransformer' が必要です

意味わかりますか？ABCでなく漢字かな文字だから一見日本語のようにみえるが、まったく意味不明です。

このメッセージを見てわたしは「`IDocTransformer` というモジュールが見つからないよ」とVBAが指摘しているのかと疑った。半角アルファベットでなく全角文字をタイプしちゃったかと疑って何度も打ち直したがそうではなかった。このメッセージを手掛かりにネットを検索した。

>`VBA コンパイル エラー オブジェクトモジュールには インターフェイス 用の が必要です`

とキーを指定してググったが、役立つページは見当たらなかった。

ふと思い立って

>`VBA error object module interface`

とキーを指定したら、[１つだけStack OverflowのURL](https://stackoverflow.com/questions/3171324/implementing-my-own-interface-in-vba-error-object-module-needs-to-implement) がヒットした。それによると同じメッセージが英語では下記のように表示されるらしい。

>Compile error:
>Object module needs to implement 'Transform' for interface 'IDocTransformer'

おや？これなら意味がわかる。VBAは `IDocTransformer` モジュールが存在していることは承知していて、そのなかに `Transform` メソッドの定義があるべきだと承知しているが、 `Transform` が見つからない、とこの英文メッセージは言っている。

だから `IDocTransformer` モジュールのなかの `Transform` メソッドの書き方が間違っているかもしれないとアタリをつけて、コードを見直したら見つけました。 `IDocTransformer` モジュールを書き間違えていた。

```
Public Function Transform( _
```

じゃなくて

```
Public Function IDocTransform_Transform( _
```

と書くのが正解だった。

## おすすめ

VBAの日本語のエラーメッセージが意味不明だったら誤訳を疑え。英語原文のメッセージならきっとあっさり意味が通じる。

ちなみにわたしのWindow10のＰＣでVBAのメッセージを英語で表示させるには次のような設定が必要でした。

(1) Windos10に英語（米国）のLanguage Packをインストールした

![OSSettingslanguage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52995/74a95bf6-2153-ba34-d891-5fdc4875e8bf.png)

(2) Excelのオプションで優先的に英語で表示するよう設定した

![ExcelOptionLanguagepng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52995/3ccebef7-b281-87ed-c199-e3c3efe6734a.png)

OSの再起動、Excelの再起動を何回か繰り返しました。
統計学でビジネスはどう変わる？

# はじめに
IT×ビジネスという視点で週1本記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiita.com/7_inai_)
# 統計学とは
統計学とは __統計に関する学問__ のことです。(そのままですが、、、)
近頃、データサイエンティストというデータ分析を専門とする職種の名前をよく耳にしますが、それだけ統計学を扱えるエンジニアが重宝されています。
データサイエンティストが増えた背景には、__IoTとビッグデータ__ の発展があります。様々な機器がIoT化し、そのIoT機器から収集した情報をビッグデータとして扱うようになりました。しかし、せっかく集めたデータも活用することができなければ意味がありません。では、IoTで集めたビッグデータを活かすことでどういったことができるのでしょうか？
# 統計学でビジネスがどう変わる？
- 仮説からデータへ
データの取得に多大なコストと時間を要していた時代は、大量のデータを取得できない代わりに仮説を立てて検証するというサイクルを回すことが一般的でした。しかし、仮説を考えると「Yes/Noの2択で答えられるクローズド」な質問になってしまいがちです。`データを有効活用することで仮説に縛られずにオープンな答えを見つける` ことができます。
- 機械ごとの生産精度の違いの測定
工場では、__複数の機械で同じモノを大量に__ 生産する必要があります。しかし、実際の現場では、不良率が高い機械や、停止回数が多い機械などそれぞれの特徴があります。統計学を用いてその特徴から傾向を見つけることができれば、より安定した設備の稼働をすることが可能です。
- アンケートの有効活用
高評価が多い製品が一番売れるとは限りません。過去のアンケート結果と照らし合わせ高評価としている人の性別や年齢等色々なデータの兼ね合いまで、単純にアンケートの結果を見るだけでは発見することができない情報まで統計学を使って判断する必要があります。
# 終わりに
情報量の増加に伴い、データサイエンティストの需要はかなり増加しています。しかし、データサイエンティストは、データの成形・データの解釈・ビジネス的に価値を出すという，3種類の全く別のスキルが必要になるため、データサイエンティストの数は全く足りていません。教育機関でもデータサイエンスを扱う学部が増加していることもあり、データサイエンティストの重要性は世界的に増加していくでしょう。
最後までお付き合いくださりありがとうございました。
Pandas.DataFrameとNumPy.ndarray間の変換

# はじめに
データ処理の際まずは```Pandas.DataFrame```としてcsvやHTMLを読み、```NumPy.ndarray```で数値計算という流れが多い（気がする。）
Pandas.DataFrameで読んだもののNumPy.ndarrayに変換できない、、、などかなり苦戦したので、二者間のやり取りの覚書を置いておきます。
```python:
import pandas as pd
import numpy as np
```
# 結論
:::note info
Pandas.DataFrame(```df```) ↔ Numpy.ndarray(```arr```)の相互変換

Pandas.DataFrame → NumPy.ndarrayは```arr = df.to_numpy()```
NumPy.ndarray → Pandas.DataFrameは```df = pd.DataFrame(arr)```
:::

# 注意点

:::note warn
Pandas.DataFrameからNumPy.ndarrayに変換するとラベル情報がなくなります。
NumPy.ndarrayからPandas.DataFrameに戻す際は必要に応じてcolumnsとindexを定義してあげるとよさげ。
```python
df = pd.DataFrame(arr,
                  columns = ["a","b","c"],
                  index = ["u","v","w"])
```
:::


# Pandas.DataFrame → NumPy.ndarray

```python:pandas→numpy
# dictionaryからPandas.DataFrameを定義する
dict1 = {"a":[1,2,3],"b":[1,2,3],"c":[1,2,3]}
df = pd.DataFrame(dict1)
print(df)

#    a  b  c
# 0  1  1  1
# 1  2  2  2
# 2  3  3  3

# Pandas.DataFrameをNumPy.ndarrayに変換する
arr = df.to_numpy()
print(arr)

# [[1 1 1]
#  [2 2 2]
#  [3 3 3]]
```




# NumPy.ndarray → Pandas.DataFrame
```python:numpy→pandas
# listからNumPy.ndarrayを定義
list1 = [[1,2,3],[1,2,3],[1,2,3]]
arr = np.array(list1)
print(arr)

# [[1 2 3]
#  [1 2 3]
#  [1 2 3]]

# NumPy.ndarrayをPandas.DataFrameに変換する
df = pd.DataFrame(arr,
                  columns = ["a","b","c"],
                  index = ["u","v","w"])
print(df)

#    a  b  c
# u  1  2  3
# v  1  2  3
# w  1  2  3
```
ReactでGoogle Analyticsの独自イベントを使う

ReactにGoogle Analyticsの独自タグを埋め込んだときのメモです。

# 1. FirebaseコンソールからAnalyticsの情報を取得
Firebaseコンソールにログインし、下記画像の、、
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/3f7c7249-c5e3-e571-31ca-bc87d9ccebcb.jpeg)

下の方にある下記画像に記載されているコードをコピーし、
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/ee37e9e5-3af6-4b87-6d27-85cb4e66090b.jpeg)

新規作成したGoogleAnalytics.jsに貼り付けます。(ファイル名は何でも可)
GoogleAnalytics.jsをReactのsrc直下に配置します。
```Javascript:GoogleAnalytics.js
import { getAnalytics } from "firebase/analytics";
import { initializeApp } from "firebase/app";

const AnalyticsConfig_prod = {
  apiKey: "aaaaaaaaaaaaaaaaaaa",
  authDomain: "bbbbbbbbbbbbbbbbbb",
  projectId: "cccccccccccc",
  storageBucket: "dddddddddddd",
  messagingSenderId: "eeeeeeeee",
  appId: "fffffffff7",
  measurementId: "gggggggggg",
};

const app = initializeApp(AnalyticsConfig_prod);
export const analytics = getAnalytics(app);
```

# 2. FirebaseライブラリをReact環境にインストール
```
npm install firebase
```

# 3. 本番環境と開発環境の切り替え
必要に応じて、Analyticsをドメイン名で切り替えるようにしておきます。

```Javascript:GoogleAnalytics.js
import { getAnalytics } from "firebase/analytics";
import { initializeApp } from "firebase/app";

const AnalyticsConfig_prod = {
  apiKey: "aaaaaaaaaaaaaaaaaaa",
  authDomain: "bbbbbbbbbbbbbbbbbb",
  projectId: "cccccccccccc",
  storageBucket: "dddddddddddd",
  messagingSenderId: "eeeeeeeee",
  appId: "fffffffff7",
  measurementId: "gggggggggg",
};

const AnalyticsConfig_stage = {
  apiKey: "hhhhhhhhhhhhh",
  authDomain: "iiiiiiiiiiiiii",
  projectId: "jjjjjjjjjjjjjj",
  storageBucket: "kkkkkkkkkkkk",
  messagingSenderId: "lllllllllll",
  appId: "mmmmmmmmmmmmmmm",
  measurementId: "nnnnnnnnnnnn",
};

let app;
if (document.domain === "xxxxxxx.yyyy.com") {
  app = initializeApp(AnalyticsConfig_prod);
} else {
  app = initializeApp(AnalyticsConfig_stage);
}

export const analytics = getAnalytics(app);
```

# 4. 各ページでイベント送信処理を実装
```Javascript:hoge.js
import { logEvent } from "firebase/analytics";
import { analytics } from "../GoogleAnalytics";
    ：
  const buttonClicked = () => {
    logEvent(analytics, "xxx画面のボタン押下");
  };
    ：
  useEffect(() => {
    logEvent(analytics, "xxx画面を表示");
  }, []);
    ：
など
```

リアルタイムではないのでコンソールに結果が表示されるまで1日かかります。下記のようにイベント名のところに独自イベント名が表示されます。
![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/d64d5db7-4b63-0b20-f800-d0dfba62704d.jpeg)
`variant`メソッドを使ったが画像が表示されない現象に対処する! with Rails7, Active Storage

## 概要

Railsチュートリアルを`Rails 7`で実装に挑戦。
そしてRailsチュートリアルでも登場してくる`variant`メソッド。(第13章)
こちらを使って投稿した画像を表示しようとしたが、なぜか表示されない現象が発生。

![qiita_error_pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459618/d6953011-398f-6f40-48f1-b32c8387241a.png)

さてこの現象と向き合うことにしよう...

## 結論

解決するためには以下の2通りある。簡単だ。

1： `vips`ライブラリをインストールする

```bash:ターミナル
$ brew install vips
```

2： 明示的に`mini_magick`を指定する

```ruby:config/application.rb
# ===== 省略 =====
module RailsTutorialApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0
    # ===== 以下を追加 =====
    config.active_storage.variant_processor = :mini_magick

# ===== 省略 =====
  end
end
```

## Why?

まず、前提として画像の加工には`ImageMagick`のインストールが必要だ。

```bash:ターミナル(Mac)
$ brew install imagemagick
```

インストールが完了したら次はGemが必要になる

```ruby:Gemfile
gem "image_processing"
gem "mini_magick"
```

＊Railsチュートリアルを進めている人は、指定のバージョンを明示的にするべきかもしれません。

```bash:ターミナル
$ bundle install
```

`gem "image_processing"`を導入することで冒頭のActive Storageが提供する`variant`メソッドを使えるようになります。

>...so you must add gem "image_processing" to your Gemfile if you wish to use variants.
>引用：[ActiveStorage::Variant < Object](https://api.rubyonrails.org/classes/ActiveStorage/Variant.html)

ただし、`Rails 7`ではデフォルトで`vips`ライブラリが使われるようになっているみたいです。
*上記のRailsAPIドキュメントではMiniMagicとなってますが...

> ...and have config.load_defaults 7.0 set in config/application.rb, then your app will use vips by default.
>引用：[Could not open library 'vips.42'; Could not open library 'libvips.42.dylib'](https://stackoverflow.com/questions/70849182/could-not-open-library-vips-42-could-not-open-library-libvips-42-dylib)

というわけで、結論に戻ってくるわけだが

1： `vips`ライブラリをインストールする

```bash:ターミナル
$ brew install vips
```

2： 明示的に`mini_magick`を指定する

```ruby:config/application.rb
# ===== 省略 =====
module RailsTutorialApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0
    # ===== 以下を追加 =====
    config.active_storage.variant_processor = :mini_magick

# ===== 省略 =====
  end
end
```

結果...上手く行った!!!

![qiita_correct_pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459618/8fd54e6c-247f-dcb5-7ac7-e3ba20a77ef3.png)


## おまけ

ちなみに私の場合、投稿直後のログはこのようになっていた。(一部抜粋)

```bash:ログ
# ==== 省略 =====
22:04:32 web.1  | LoadError (Could not open library 'vips.42': dlopen(vips.42, 0x0005): tried: 'vips.42' (no such file), '/usr/local/lib/vips.42' (no such file), '/usr/lib/vips.42' (no such file), '/Users/***/my_app/rails_tutorial_app/vips.42' (no such file).
22:04:32 web.1  | Could not open library 'libvips.42.dylib': dlopen(libvips.42.dylib, 0x0005): tried: 'libvips.42.dylib' (no such file), '/usr/local/lib/libvips.42.dylib' (no such file), '/usr/lib/libvips.42.dylib' (no such file), '/Users/***/my_app/rails_tutorial_app/libvips.42.dylib' (no such file)):

```

やはり、デフォルトでは`vips`ライブラリを使用しているみたいだ。
LambdaからDynamoDBへの大量データ投入

# DynamoDBへの大量データ投入

- Pythonではやったことがあったけど、Node.jsではやっていないかったのでやってみると、高速だった。 1putごとにawaitしないから高速ですね。
- https://dev.classmethod.jp/articles/nodejs-dynamodb-scan-stream/ クラスメソッドさんの記事まんまできる
    - 「スクリプトで50万件のテストデータを作成」の箇所のtsをjsに変える

- DynaomoDBテーブルは、オンデマンドキャパシティを使う
- Pythonの並列処理を作成するのは苦手だけど、Node.jsならばPromise.all() で非同期処理で同時に実行できCPUパワーを十分に使える

## AWS Lambdaの設定
- Lambdaをメモリ1024MB、タイムアウト1分にする
- Lambda Layer使うのですが割愛します

## DynamoDB
- テーブル名 ：sugimoto-scan
- パーティションキー ：id,文字列
- ソートキー：指定なし
- 設定をカスタマイズ にて、キャパシティーモードで「オンデマンド」を選択

### 実行ロール

- 追加するポリシー（東京リージョンにDynamoDBテーブルがある想定）
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:Put*",
                "dynamodb:Update*",
                "dynamodb:BatchWriteItem",
                "dynamodb:Scan"
            ],
            "Resource": [
                "arn:aws:dynamodb:ap-northeast-1:*:table/sugimoto-*",
            ]
        }
    ]
}
```

### ソース

```js

const { DynamoDB } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocument } = require("@aws-sdk/lib-dynamodb");
const { v4 } =require("uuid");

const ddb = new DynamoDB({
  region: 'ap-northeast-1',
})
const ddbDoc = DynamoDBDocument.from(ddb)

async function main() {
  for (let i = 0; i < 10; i++) {
    await Promise.all(
      Array.from({ length: 100 }).map(async () =>
        ddbDoc.put({
          TableName: 'sugimoto-scan',
          Item: {
            id: v4(),
            name: "ABCDEFGHあああああ-～いいいいいえええええええ1234567890",
          },
        })
      )
    )
  }
}


exports.handler = async (event) => {
   
    await main();
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
```

## 実行時間
- コールドスタートで2500ms, ウォームスタート1400msで終わるので、forループ回数は10倍も余裕
- Lambdaの実行時間を15分まで延ばせば さらに増やすことが可能

## 注意点
- オンデマンドキャパシティなので書込み料金がまあまあかかる
- プロビジョンドだと、エラーになります（キャパシティを使い切ってしまう）
    - プロビジョニングモードでは、書込み量が上限に引っかかってしまいエラーになる
Go言語の英語チュートリアル ペライチ Hello world　go version go1.18.3 windows


大学でCのTAをやって以来ですが、Go言語を勉強してみます。

# チュートリアルの概要
Windowsで、cmdとVSCode(要ダウンロード)を使いました。
Go version : go1.18.3 windows/amd64

#1 Hello worldの表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/34625e78-333a-b6f9-4b52-35464b7afb52.png)


# 参考リンク
Goのgetting started（入門講座）
https://go.dev/doc/

# Installing Go
## 1. Goのインストール
 windows版をインストール

### 1.2 VSCodeのインストール
　https://zenn.dev/em0/articles/41bbfb9aae6bb9240fa9
　を参照。
　https://code.visualstudio.com/docs/?dv=win

### Step3: VSCodeの設定でエラーになる。
　`command 'go.tools.install' not found` 
なぜか`>go mod init v2 `でエラーが出なくなった。
```
>go mod init
go: cannot determine module path for source directory C:\Users\skane\hello (outside GOPATH, module path must be specified)

Example usage:
        'go mod init example.com/m' to initialize a v0 or v1 module
        'go mod init example.com/m/v2' to initialize a v2 module

Run 'go help mod init' for more information.
```
Goのワークスペース"go env"コマンドで確認できる
>go env
GOPATH=C:\Users\skane\go。


## 2. Tutorial: Get started with Go
・cmdを開く
・helloディレクトリを作る

### Enable dependency tracking for your code.
　"go mod init"　してみる。
　goのmoduleを作るコマンド。codeを実行するときに必要。
　https://pkg.go.dev/cmd/go#hdr-Initialize_new_module_in_current_directory

### In your text editor, create a file hello.go in which to write your code.
 テキストエディタ(VSCode)でhello.goを作る。
　File ＞　New text file ＞select a language "go" 
  Ctrl + S 
　C:\Users\skane\hello　に保存する。

### Paste the following code into your hello.go
 package main : fanctionの塊。
 import : fmt 　fmtパッケージをインポートする。 stringとか数字とか
 function main : コンソールに表示されるメイン。

### Run your code to see the greeting.

```
C:\Users\skane\hello>go run hello.go
Hello, World!
```
できた！

## Call code in an external package　他の人の作ったパッケージを使う。
pkg.go.dev siteで、moduleを見つけれて自分のプログラムに使える。
go mod tidy コマンドを入力すると、必要なmodがダウンロードされる？
　- quote (rsc.io/quote/v4)

```
C:\Users\skane\hello>go run rsc.go
Don't communicate by sharing memory, share memory by communicating.
```

失敗しているっぽいけど、これでいいらしい。
【Tableau】凡例の色が多いときの小技

# 今回の解消したい課題
- 可視化をした際に凡例(色)が多い場合の解決方法の1例を紹介
        - 【条件】関連性のある2つの凡例を利用している場合に有効な可視化
# 環境
Tableau Desktop 2022.1.3
データソース：サンプル - スーパーストア
***
【テーマ】：四半期ごとの売上合計を可視化
1. まずは四半期ごとの売上を可視化してみる
Tableauではおなじみのサンプル - スーパーストアを利用
![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/a53ed7da-18f5-cdb1-997b-327c486eb6ec.png)
サブカテゴリの凡例が多く色がたくさん利用される

2. そこでカテゴリ別を __行__ に追加してみる
![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/28cb639a-de82-b3d2-1ac3-e4997cee5a57.png)
先程よりは見やすくなったが、まだ色が多く傾向をみることが難しい
↓効果的な可視化をしてみる

3. カテゴリを __詳細__ に入れる
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/a8d463c1-7289-6f33-e888-10549bc712e1.png)
まずは行からカテゴリを外し
詳細にカテゴリを入れる
このままだと可視化としては変化なし
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/a2846cba-2066-a094-aac0-e1cc49c1ed35.png)
__詳細__ をクリックし __色__ に変更
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/c17d15e8-8163-99c4-cc8c-c0a5c55d600d.png)
すると、右の凡例が「サブカテゴリ」から「サブカテゴリ、カテゴリ」に変化
4. マークの順番を変更
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/44dd8f15-d293-2cd7-2432-a77e2cd59180.png)
カテゴリとサブカテゴリの順番を入れ替える
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707779/4a5d5a4f-0d43-1420-06a8-b12d9a6a0833.png)
するとカテゴリ毎に色が分類され、サブカテゴリ毎にグラデーションで表示されるように変化
これで傾向を見やすく変化することが可能となった

***
あくまで個人的な修正方法なので参考になれば...
Tableauの操作は奥が深い。
【PHP】null処理方法の使い分け（isset、empty、is_null）

## はじめに
PHPにおけるnullの処理方法についてまとめたいと思います。

動機として、PHPには意外とnullを判定する方法が多く存在しているのですが、
落とし穴も多く、それぞれの方法をまとめ、使い分ける必要があるのではないかと考えました。
実務ではないのですが、PHPの開発でエラーが解決できずにハマってしまいました。

## 対象者
- 駆け出しエンジニア
- 入社1年半くらいまでのPHPer
- エンジニアではないが、PHPを最近始めた

かなり基本的なことで、公式のドキュメントに書かれていることをまとめたものになります。
ある程度経験のある人には、あまり面白い内容ではないと思われます。

## 本題
### null判定方法一覧
- `isset()`を使う
- `empty()`を使う
- `is_null()`を使う
- `$variable === null`

上記が挙げられると思います。
他にもこんな方法で`null`を判定できるよ！という方法があれば教えていただきたいです。

### isset()を使う
`isset()`は変数が定義されており、値が`null`でないことを確認します。
そのため空文字が含まれている場合には`true`になります。
``` PHP
$var = '';
isset($var); // TRUE
$var = "test";
isset($var); // TRUE
unset($var);
isset($var); // FALSE
$var = null;
isset($var); // FALSE
```
注意点として変数でしか使えないという点があります。
そのためたとえば下記のようにある値を返す関数を`isset()`を使用してチェックするとエラーになります。
``` PHP
function returnNull()
{
    return null;
}

isset(returnNull()) // エラー
```
### empty()を使う
`empty()`は変数が空であるかどうかを検査します。
これはつまり`null`だけでなく、変数が`false`とみなされる場合にも空だと判定されます。
``` PHP
$var = '';
empty($var); // TRUE
$var = 0;
empty($var); // TRUE
$var = 'test';
empty($var); // FALSE
$var = null;
empty($var); // TRUE
```
`isset()`と違い、厳密な`null`以外も`true`として通してしまうため、
注意が必要です。（というよりアンチパターンにしているPJもあるかもしれません。）
### is_null()を使う
`is_null()`は`isset()`と逆の働きをします。
つまり値が`null`の時に`true`と見做され、それ以外は`false`になります。
```php
$var = '';
is_null($var); // FALSE
$var = 0;
is_null($var); // FALSE
$var = 'test';
is_null($var); // FALSE
$var = null;
is_null($var); // TRUE
unset($var);
is_null($var); // TRUE
```
### $variable === null
最後に紹介する方法は最も原始的な方法だと思います。
ずばり値が`null`かどうかを直接チェックするというものです。
この方法のメリットは変数だけでなく、関数の戻り値もチェックすることができます。
先に紹介した方法は変数が定義されていることを前提としているため、関数を渡すとエラーになります。

この方法を使うことで関数の戻り値もチェックできます。
```php
$var = '';
$var === null; // FALSE
$var = 0;
$var === null; // FALSE
$var = 'test';
$var === null; // FALSE
$var = null;
$var === null; // TRUE
returnNull() === null // TRUE
```
## まとめ
基本的には`isset()`や`is_null()`を使用して、関数の戻り値で分岐したい場合は`returnNull() === null`を使うという使い分け方でいいのかな？と思いました。
VBAテンプレート　開始位置が異なる複数の表を集計する

## 概要

自分用です。
Excelにパスを記載したファイルを上から順番に開いて、表をコピーしていきます。

・行ごとコピペするだけなのでカラムごとの対応はしていません。
・開始する行を指定して行をコピーしていきます。
・開始する行は完全一致で検索をかけるのでファイルごとに開始位置が異なっていても問題ありません。
・コピー後１列名にコピー元のファイル名を記載します。

## シートの作成
シートは２シート作成します。
 ・「ファイル一覧」シート
 ・「取得結果」シート

表は「ファイル一覧」シートに2つ作成します。
表１　コピー開始行の指定
A列にタイトルを記載
B1セル：検索文字（完全一致）
B2セル：数値（検索したセルの行＋Ｂ2セルの数値　からコピーを開始する。空白行になるまでコピーを続ける）

表２　検索対象ファイル一覧
ヘッダは１行目、値は２行目から記載します。
D列：操作の要否（操作不要なら×を記載）
E列：操作したいファイルのパス
F列：結果を記載する（今回はコピーした行数）

図　「ファイル一覧」シート
![VBA_特定行取得_2022-06-30 221625.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2550991/19049f45-fc50-f391-3f88-89b830e05159.png)

※「取得結果」シートにはマクロを実行した分だけ行が継ぎ足されていきます。
最初から集計しなおしたい場合は値を手動で消す必要があります。


## VBAコード
Moduleは2つ作成します。

Module1
ファイルを開き処理を実施する関数を呼び出す

```
Sub Excel表集計()
Application.ScreenUpdating = False
Dim ファイル一覧シート As Variant
Set ファイル一覧シート = ThisWorkbook.Sheets("ファイル一覧")
Dim 操作ブック As Workbook
Dim 結果 As String

On Error GoTo エラー

For filei = 2 To ファイル一覧シート.Range("E10000").End(xlUp).Row

    ファイル一覧シート.Range("F" & filei).Value = "未処理"
    
     If Not ファイル一覧シート.Range("D" & filei).Value = "×" Then
        Workbooks.Open ファイル一覧シート.Range("E" & filei)
        Set 操作ブック = ActiveWorkbook
        '処理の実行
        結果 = ファイル操作(操作ブック)
        操作ブック.Close SaveChanges:=False
        ファイル一覧シート.Range("F" & filei).Value = 結果
      End If
      GoTo skip

エラー:
    ファイル一覧シート.Range("F" & filei).Value = "ファイル開かず"
skip:
Next
End Sub


```

Module1
ファイルを開き処理を実施する関数を呼び出す

```
Function ファイル操作(ByRef 操作ブック As Workbook) As String

On Error GoTo エラー

'好きな処理を記載

Dim ファイル一覧シート As Variant
Set ファイル一覧シート = ThisWorkbook.Sheets("ファイル一覧")
Dim 取得結果シート As Variant
Set 取得結果シート = ThisWorkbook.Sheets("取得結果")

Dim 結果 As String
結果 = "結果なし"
Dim コピーした行数 As Integer
    コピーした行数 = 0
Dim 操作シート As Worksheet
Dim 操作対象検索セル As Range, 操作行 As Integer


    For Each 操作シート In 操作ブック.Worksheets
        
        Set 操作対象検索セル = 操作シート.Cells.Find(ファイル一覧シート.Range("B1"), LookAt:=xlWhole)
                        
        If Not 操作対象検索セル Is Nothing Then
            操作行 = 操作対象検索セル.Row + ファイル一覧シート.Range("B2")
            
            Do While Len(操作シート.Cells(操作行, 操作対象検索セル.Column)) > 0
                Dim 貼り付け先行 As Integer
                貼り付け先行 = 取得結果シート.Range("A10000").End(xlUp).Row + 1
                操作シート.Rows(操作行).Copy Destination:=取得結果シート.Rows(貼り付け先行)
                取得結果シート.Range("A" & 貼り付け先行).Insert (xlShiftToRight) 'セルを挿入　右にずれる
                取得結果シート.Range("A" & 貼り付け先行) = 操作ブック.Name
                コピーした行数 = コピーした行数 + 1
                操作行 = 操作行 + 1
            Loop
        End If
        

    Next 操作シート
    
    If コピーした行数 > 0 Then
        結果 = コピーした行数
    End If


ファイル操作 = 結果
Exit Function

エラー:
ファイル操作 = "エラー発生"

End Function



```

## おまけ
集計した表の表記ゆれをチェックできるVBAを作成しました。
一緒に使うと便利だと思います。

[VBAテンプレート　表記ブレチェッカー](https://qiita.com/cuvskr/items/f2240681fd12b268365c)
プログラミングの勉強かつ転職活動ができる！？

## プログラミングの勉強かつ転職活動ができる？
今日は自分が教わったおすすめの学習サイトをお伝えします。知っている方もいらっしゃるかもしれませんが、もし知らなければぜひ見てみてください。

### Paizaを利用すれば学習と転職活動ができる？
paizaのアプリを使用することによってフロントエンド、バックエンドに関わらずさまざまな言語の勉強をすることができます。自分の学習したい言語、転職したい先に合わせた学習できます。
また、自分のスキルに応じたチェックテストも行うことができるため、自分の今の実力を試したい方にも是非チェックしてください。


### 以下のリンクから是非見てみてください。
https://paiza.jp/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1034521/b7c00fd9-c798-e602-247a-72fec854dfc7.png)
AWSマネジメントコンソールにサインインできないときにやること

# 概要
AWSマネジメントコンソールにサインインできないときのメモ

# IAMユーザーの場合
- MFA認証の時刻同期。複数回ログインに失敗すると画面上で再同期を促される。
  https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_sync.html
- パスワード忘れや他の課題がある場合は、管理者（ルートユーザー）か他のIAMユーザーでコンソールにサインインして対処する。

# ルートユーザーの場合
- MFA認証の時刻同期。IAMユーザーと同様。
- パスワードの変更。画面上で操作可能。
  https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_passwords_change-root.html
- MFAデバイスを削除。AWSサポートへ要請する。
    - https://support.aws.amazon.com/#/contacts/aws-mfa-support
    - 後日、アマゾンジャパン合同会社から電話
    - 登録したメールアドレスを口頭で読み上げる
    - 送付されたワンタイムパスワードを読み上げる
    - 電話でのやり取りが終了し以下のメールが届く無事MFAデバイスの削除が完了する
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228134/669eb55a-62c4-a911-23ee-86182c138715.png)

# 参考
- [MFA デバイスの紛失および故障時の対応](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html)
【AWS】Lambda + API Gatewayを触ってみる【Lambda編】


LambdaとAPI Gatewayを使って簡単なAPIを作成してみます。
AWSはほとんど触ったことがないため、内容としては初歩の初歩となります。
今回はLambdaで関数を作成していきます。

# Lambda関数を作成
まずはLambda関数を作成していきます。
マネジメントコンソールでAWS Lambdaの関数のページを開いて、「関数の作成」を押下します。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/8baf5339-2848-fec0-58f8-e7558d855f92.png)

「一から作成」を選択し、関数名を「Sample」、ランタイムは「Python 3.9」を選択します。
その他の項目はデフォルトのままとし、「関数の作成」を押下します。
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/69b080e5-177d-abb3-29ee-84dcd2c72a5b.png)

作成が完了すると、元から「Hello from Lambda!」を返すサンプルコードがあります。
今回、関数の中身はこだわらないのでサンプルコードをそのまま使用します。
![画像7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/8d9c721c-01be-29b9-12e1-2cec6732fb29.png)

# Lambda関数のテスト
Lambda関数のテストを実施してみます。
テストタブを開き、「テスト」を押下します。
![画像8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/fa22991d-eb44-e46b-3f0e-e6abd358587e.png)

テストが完了すると、実行結果とログが確認できます。（ログはCloudWatchに出力されます。）
![画像9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/c8fda8b8-6d70-ed47-2a76-4d5d0240e77d.png)
ログが出力されて関数が正常に動作していることを確認できました。
# 次回
次回はAPI GatewayでAPIを作成し、Lambda関数と紐づけて実行します。
DataFrameの列（行）番号を指定してラベルを変更 Pandas.DataFrame

# はじめに
pandas.DataFrameのカラム名やインデックス名を変えたいけど```pd.rename()```をつかうには```df.rename(columns={'before': 'after'}, index={'before': 'after'})```のように「これまでの名前」と「これからの名前」が必要になるのが面倒。

そこで列番号（行番号）を指定して名前を変更する関数を定義してみる。

```pandas```のインポート
```python:
import pandas as pd
```

# 関数の定義

```python:
def rename_iaxis(dataframe, axis, n, name):
    # axis = 0ならインデックス、axis = 1ならカラムの名前をリスト化する
    if axis == 0:
        org_namelist = list(dataframe.index)
    elif axis == 1:
        org_namelist = list(dataframe.columns)
    
    # 名前のリストのn番目をnameに変更する
    new_namelist = org_namelist
    new_namelist[n] = name
    
    # dataframeのラベルを変更する
    dataframe = dataframe.set_axis(new_namelist, axis = axis, inplace = False)
    
    # データフレームを返す
    return dataframe
```


# 呼び出し

```python:
# pandas DataFrameを作成する
org_dict = {"a":[1,2,3],"b":[4,5,6],"c":[7,8,9]}
org_df = pd.DataFrame(org_dict)
print(org_df)

#    a  b  c
# 0  1  4  7
# 1  2  5  8
# 2  3  6  9


# 1番のカラム名をzに変更する
new_df = rename_iaxis(dataframe = org_df, axis = 1, n = 1, name = "z")
print(new_df)

#    a  z  c
# 0  1  4  7
# 1  2  5  8
# 2  3  6  9
```

これでいくらか名前を変えるハードルが下がった？？？
Ubuntu20.04 VurtualBox  起動エラー対処 /sbin/vboxconfigの実行作業の流れ


* Ubuntu20.04 VurtualBoxを使っていると忘れた頃に、起動エラーが発生し、悩まされます
* こちらの記事は非常に的確で、感謝しています。
    * https://freefielder.jp/blog/2019/09/secure-boot-ubuntu-vbox.html