カテゴリー別アーカイブ: メモ

【R】カタカナの非語を自動生成する

はじめに

実験に使うために作ったのですが,結局ボツになったので,どうやってカタカナの非語を作成しようとしたのかの方法をブログの記事に書くことで成仏させたいと思います。考え方は簡単で,カタカナ語の含まれる変数と,任意の数字が入った変数を作って,後者の変数から任意に1つの数字を選び出し,その数だけカタカナ語のリストから任意に取ってきてくっつける,という感じです。よって,生成される文字列は日本語らしさとかはまったく無視されたものになります(まれに日本語っぽいものや完全に日本語のものもできますランダムなので)。

カタカナのリストを用意

まずはカタカナのリストを作ります。アルファベットとかは簡単なんですが,カタカナのリストがRのデフォルトにはない(たぶん)ので,自分で用意します。ただ,50音の表だと扱いづらいので,カタカナを縦にガーッと並んだものをコピーできたら便利だなと思っていたら,そんなサイトがありました。

http://desilysis.seesaa.net/article/423176853.html

ここにあるものをコピーして,kanaという変数に入れます。ちなみに,この記事で使う「リスト」は一般的な意味で,Rにおける「リスト型」という意味のリストではありませんのでご注意ください。

kana <-read.table("clipboard") #Windows
kana <-read.table(pipe("pbpaste")) #Mac
print(kana)


すると,こんな感じでカタカナが入った変数が手に入ります。read.tableで読み込んでるのでデータフレームになります。濁音と半濁音が抜いてあります。入れてもいいのですが,入れるとそれっぽいカタカナ語が生成されづらくなるというのが理由です。

##    V1
## 1  ア
## 2  イ
## 3  ウ
## 4  エ
## 5  オ
## 6  カ
## 7  キ
## 8  ク
## 9  ケ
## 10 コ
## 11 サ
## 12 シ
## 13 ス
## 14 セ
## 15 ソ
## 16 タ
## 17 チ
## 18 ツ
## 19 テ
## 20 ト
## 21 ナ
## 22 ニ
## 23 ヌ
## 24 ネ
## 25 ノ
## 26 ハ
## 27 ヒ
## 28 フ
## 29 ヘ
## 30 ホ
## 31 マ
## 32 ミ
## 33 ム
## 34 メ
## 35 モ
## 36 ヤ
## 37 ユ
## 38 ヨ
## 39 ラ
## 40 リ
## 41 ル
## 42 レ
## 43 ロ
## 44 ワ
## 45 ヲ
## 46 ン

任意の数字のリストを作る

次に,任意の数字のリストを作ります。もしも,4文字の非語だけで良いというような場合はこの作業はスキップしてもらってOKです。ここでは,3文字から8文字の非語を作ることにします。

kazu <-c(3:8)
print(kazu)
## [1] 3 4 5 6 7 8

これで2つの道具が揃ったので,あとはこの2つを組み合わせるだけです。

カタカナをランダムに組み合わせる

非語をいれるハコを用意

まず,できあがった非語を入れるためのハコを用意します。ここでは,100個作ることにしましょう。 nonword という列に,0を100個いれてます。

dat<- data.frame(nonword=rep(0,100))
print(dat)
##     nonword
## 1         0
## 2         0
## 3         0
## 4         0
## 5         0
## 6         0
## 7         0
## 8         0
## 9         0
## 10        0
## 11        0
## 12        0
## 13        0
## 14        0
## 15        0
## 16        0
## 17        0
## 18        0
## 19        0
## 20        0
## 21        0
## 22        0
## 23        0
## 24        0
## 25        0
## 26        0
## 27        0
## 28        0
## 29        0
## 30        0
## 31        0
## 32        0
## 33        0
## 34        0
## 35        0
## 36        0
## 37        0
## 38        0
## 39        0
## 40        0
## 41        0
## 42        0
## 43        0
## 44        0
## 45        0
## 46        0
## 47        0
## 48        0
## 49        0
## 50        0
## 51        0
## 52        0
## 53        0
## 54        0
## 55        0
## 56        0
## 57        0
## 58        0
## 59        0
## 60        0
## 61        0
## 62        0
## 63        0
## 64        0
## 65        0
## 66        0
## 67        0
## 68        0
## 69        0
## 70        0
## 71        0
## 72        0
## 73        0
## 74        0
## 75        0
## 76        0
## 77        0
## 78        0
## 79        0
## 80        0
## 81        0
## 82        0
## 83        0
## 84        0
## 85        0
## 86        0
## 87        0
## 88        0
## 89        0
## 90        0
## 91        0
## 92        0
## 93        0
## 94        0
## 95        0
## 96        0
## 97        0
## 98        0
## 99        0
## 100       0

forで繰り返す

では,for文を使って,1行目から100行目まで順番に非語をぶちこんでいきます。sample関数は,次のような引数をとります。

sample(x,size,replace=FALSE,prob=NULL)

  • x ->無作為抽出元のベクトル
  • size ->無作為抽出で何個とってくるか
  • replace ->重複ありでとってくるか(同じものが2回でてもいいかどうか)
  • prob ->xの要素が抽出される確率

ここではprobは特にこだわらなくてOKですね。重複はなしでいってみましょう。xはkanaでsizeは3~8がランダムに出てほしいので,ここにもsample関数を使いましょう。つまり,kazuという変数から任意に1つ選んで,その数字の長さの非語を作ろうということです。3がでたなら3文字,7が出たなら7文字ということです。ここを固定した数字にすれば,その文字数の非語のみができます。ということで,以下のような感じで走らせます。

for (i in 1:100){
    dat[i,]<-   paste(as.character(sample(kana[,1],sample(kazu,1))),sep="",collapse="")
    }


kanaというデータフレームの1列目から,kazu(3~8)から選ばれた任意の数字の数だけ要素を無作為に選んできて,paste関数で合体させるということですね。一応,paste関数の中でas.character関数を使って文字列の扱いを指定してますが,なくてもたぶん動くかなと思います。

##              nonword
## 1           サカフヌ
## 2     トセヲクロヨサ
## 3   ケトカヲヤイアタ
## 4   ツヒオセコミルハ
## 5             キセア
## 6     クタロヲマヒモ
## 7       ワニレシヘン
## 8         イキニオレ
## 9           ヤイケマ
## 10    ヌラテホメムネ
## 11  ハヨスヌセリエム
## 12            カリク
## 13            フロヲ
## 14      ルテロヘサタ
## 15      テユヨマクト
## 16        ヲホロケニ
## 17          リミユソ
## 18  ホシヲリカテレミ
## 19          モメスル
## 20        ホキヤコカ
## 21    ネコオモトユレ
## 22          ワラソヲ
## 23            ニユナ
## 24        タフテモス
## 25          キノラケ
## 26            ルヨモ
## 27      トンルフヌロ
## 28        エロスヨフ
## 29  レテキアタホロハ
## 30      キリナコロヘ
## 31          アキタル
## 32        キニユミイ
## 33        トムテルネ
## 34      ホンタヨヌイ
## 35          セエシト
## 36        キテチハソ
## 37        ヌソハチエ
## 38            ヨヒマ
## 39          ハモクシ
## 40    カオトヌリフキ
## 41      ホヨオトカリ
## 42          ヤヌホト
## 43      メクユイソテ
## 44  カフトルムリレマ
## 45        ヤチツテシ
## 46            シヌメ
## 47  ムアコチワノウネ
## 48  ヲリノイヒフウミ
## 49      サムヤトシラ
## 50            ユミケ
## 51        レカフヤン
## 52      ミノリヤタホ
## 53            ツケイ
## 54  ニロネウモトソナ
## 55        レセシノラ
## 56          コヌメニ
## 57          ツユニン
## 58            クトス
## 59          スツヌリ
## 60    メユマヲウチロ
## 61            ネヨタ
## 62      ヤハケミソセ
## 63            リチキ
## 64            ハネマ
## 65          ツノウタ
## 66        ヌツセアラ
## 67          ヘサキウ
## 68      タセルユヲチ
## 69      カンシナテヨ
## 70      ラロモオヲノ
## 71  ホムニヨイリンク
## 72      トロイアネツ
## 73    ケモレクメトア
## 74            ミカセ
## 75          スホアセ
## 76  ラルマノヤキユテ
## 77      ニチノマヤイ
## 78            ワリサ
## 79      ヤラヲスソム
## 80      タトクンシア
## 81      ニフシユトヒ
## 82      トメマケヤオ
## 83        オリクツル
## 84  ラリオホメヘモシ
## 85            オヌエ
## 86        トサヌンス
## 87            ワオウ
## 88        ヒラキメノ
## 89    サエアカラハメ
## 90      ネフミナモワ
## 91            サヤフ
## 92        クヤヨイナ
## 93  コキソユクホマノ
## 94            メムヌ
## 95      オヲユカスン
## 96          ケヌニタ
## 97    ユキラチヨネテ
## 98          ヒレニエ
## 99    メワセモオネク
## 100     ヤタセンノウ


サカフヌとかテユヨマクトとかわけわからないのがたくさんできてますね。もしも,4文字の非語だけで良いということであれば,

for (i in 1:100){
    dat2[i,]<-  paste(as.character(sample(kana[,1],4)),sep="",collapse="")
}


のように, sample(kazu,1) の部分を任意の数字に入れ替えてあげることになります。そうすれば,4文字だけの非語リストが手に入ります。

dat2<- data.frame(nonword=rep(0,100))
for (i in 1:100){
    dat2[i,]<-  paste(as.character(sample(kana[,1],4)),sep="",collapse="")
}
print(dat2)
##      nonword
## 1   スメヘウ
## 2   セイオヒ
## 3   ホラリヤ
## 4   ニチメセ
## 5   ヌナメコ
## 6   ヌサトヤ
## 7   レチシイ
## 8   コフハチ
## 9   ヨヘユハ
## 10  マンツメ
## 11  ヒホソム
## 12  スヲテユ
## 13  スヒチレ
## 14  ルヒホヘ
## 15  テシフユ
## 16  ロテカウ
## 17  トノルニ
## 18  ヨホオハ
## 19  ヨキミチ
## 20  ワナヘノ
## 21  ヌヨナマ
## 22  クタンイ
## 23  ハムンシ
## 24  ネロレナ
## 25  アムネノ
## 26  ハフソト
## 27  ヨスクヌ
## 28  サスキホ
## 29  ヨワツノ
## 30  イトセム
## 31  オセンエ
## 32  ホミレル
## 33  リラハフ
## 34  ツラソカ
## 35  テチサシ
## 36  ツヲヌヒ
## 37  ヲタカム
## 38  ハアワレ
## 39  オクネケ
## 40  ミムルヤ
## 41  ヘテロホ
## 42  アサヤケ
## 43  チヤラウ
## 44  クハサケ
## 45  ンテリム
## 46  メネサム
## 47  マシトリ
## 48  クヌワマ
## 49  ナヤリロ
## 50  ナヤウン
## 51  タンナレ
## 52  メヘオテ
## 53  ソキヨニ
## 54  ソユヘタ
## 55  ルサスノ
## 56  ネウフセ
## 57  ムメシヒ
## 58  ネシムセ
## 59  ケヘシノ
## 60  ヒケルメ
## 61  メンタモ
## 62  エケチコ
## 63  ニチシヤ
## 64  テルメキ
## 65  モツロイ
## 66  エレサセ
## 67  ンスイハ
## 68  アモチセ
## 69  ノヤミネ
## 70  ヨストカ
## 71  ニヒラン
## 72  リノシナ
## 73  ハタヘス
## 74  メオヘセ
## 75  エヘミロ
## 76  トソテマ
## 77  ネイトフ
## 78  スイツヲ
## 79  カセレム
## 80  ツウコユ
## 81  ヤムニネ
## 82  サメネン
## 83  シテフケ
## 84  セロヲヌ
## 85  マシスエ
## 86  オンヤナ
## 87  トルキエ
## 88  ソヘトヌ
## 89  ヒカクニ
## 90  クケコツ
## 91  ヌリルホ
## 92  トサセリ
## 93  コロツム
## 94  ホリトク
## 95  モヲネヘ
## 96  ケシヨフ
## 97  テレメヘ
## 98  ナハヲモ
## 99  オレトル
## 100 レノケマ

おわりに

この記事では,Rを使ってカタカナの非語をランダムに生成するということをやってみました。いつか誰かの役に立ちますように。

なにをゆう たむらゆう。

おしまい。

余談

実は,以前RmarkdownからWordpressに直接流し込む方法という記事を書いていて,その方法を使ってRmarkdownで書いたものをブログ記事にしようとしました。ところが,knit2wp関数がうまくいってないのかエラーが出てしまって,結局うまく行きませんでした。これのために時間溶かすのもなんだかなと思ったので,HTMLで書き出して,それをテキストエディタで開いたものをコピペしてこの記事をつくりました(トホホ

Macの移行システムのあとDropbox沼にハマった

新しくMacbook Pro (13-inch, 2020, Four Thunderbolt 3 ports)を買いました。Macbook Air 2013 midからの乗り換えで,Macの移行システムを使ってデータ移行しました。MBA側でOSのアップデートがされていなくて何度も失敗したんですが,最新版にしたらWifiでもできました。Wifiでは無理っていう記事もたくさん見たんですが,5時間くらいで終わったと思います。私は基本的にファイルはOne DriveやDropboxに保存しているので,それらのファイルは移行対象から外して,あとで同期すればいいやと思っていました。

ところが,これがのちに問題になることに….

最終的に,下記の掲示板に掲載されているターミナルのコマンドを打ち込んだら解決しました。日本語では解決策を見つけられなかったので,英語ができてよかったと思いました。

https://apple.stackexchange.com/questions/128551/dropbox-asking-for-permissions-to-wrong-folder-after-changing-account-name

実は,このページに辿り着く前に,「まさにこの状況と同じ!」という相談内容が書き込まれていたページも見つけたんです。ただ,そこで示された方法を試しても解決されず。

https://www.dropboxforum.com/t5/Dropbox-files-folders/Can-t-start-dropbox-because-of-permission-error/td-p/22462

Dropboxの公式でも,上の掲示板で提案されているのと同じようにターミナルに打ち込む方法が書かれていたけど,それではうまくいきませんでした。

https://help.dropbox.com/ja-jp/installs-integrations/desktop/move-dropbox-folder

要するに,移行するときにアカウント名被りがあって,もともとは,Users/yu/~だったのに,Users/yu1/~というようになってしまっていたのです。そこで,アップルの公式サイトに書かれていた方法でyuに戻すという作業をしました。

macOS のユーザアカウントやホームフォルダの名前を変更する

変更はうまくいったものの,Dropboxを立ち上げるとUsers/yu1/Dropbox~というディレクトリを作ろうとして,「そんなものはないぞ」というエラーが出て詰んだということでした。

ターミナルから,Dropboxがディレクトリを作る場所を変更してあげることでうまくいったということですね(ターミナルのコマンドのそれぞれの意味はよくわかってない)。

なにはともあれ,解決してよかったです。また何年後かに同じ問題にぶち当たるかもしれないので,備忘録として。

なにをゆう たむらゆう。

おしまい。

MicrosoftのSwayっていうアプリがなんかいいぞ

はじめに

ようやく自分の授業準備も少しずつ進められるようになってきました。気晴らしにメモがてらの記事を更新します。LMSの使い方をLMSで説明しちゃだめよなぁということを考えていて,なんかそういうときに簡単に資料作れないかなと考えていたら,Swayが良さそうという事がわかったという話です。Apple派の人はここでおさらばのようですね(嘘)。

LMSにLMSの使い方を載せるのはなぜだめ?

LMSにログインしてからの設定の説明等をLMSの内部に資料としてアップするっていうのは,LMSに資料ページがあるとやってしまいがちだったりするんです。ただ,実際に資料を見る側になると不便だよねという話です。

特に,多くの学生はスマホでLMSを開くことが多いでしょう。そのとき,スマホでLMSの資料を見ながらスマホで作業するってどうやるの?っていうことになりがちですよね。特に,LMSを複数タブで開いて作業するとエラーが発生する原因にもなるので回避しなくてはいけません。ということで,そういったマニュアルとか,参照するための資料はLMSの中にリンクを張って,外に飛ばすようにしたほうが健全だなと思います。

簡単なのは,Word等で文書ファイルを作り,それをPDFにしてクラウドサービスにアップロードし,その共有リンクをLMSに貼る方法です。これなら,リンクを開いたらLMSの外に一旦出ますので,マニュアルや参照資料を見ながらもとのLMSで作業することができます。

Swayがよさげ

ただ,マニュアル的なものってスクショの貼り付けがどうしても多くなるので,パワポだったりワードだったりで作るのって結構めんどくさいんですよね。そんなとき,勤務先の大学が契約しているOffice365のアプリの1つであるSwayというものを見つけました。

ブラウザベースのプレゼンアプリで,機能が限定されている分だけシンプルに作業できるなというイメージでした。実際に,Swayを使って作ってみた資料がこちら

インタラクティブな資料になるので,資料を見る側で,表示方法を変えることができるのがいいですね。歯車アイコンをクリックすると,縦スクロール,横スクロール,プレゼン資料という3つのレイアウトが選べます。プレゼン資料にすると,自動で勝手にアニメーションつけることもできます。デザインの種類はテンプレになっているものがいくつかあって,作るときに選ぶことになります。

新規作成時の最初は下記画像のような画面です。左上を見るとわかるように,プレゼンの内容をいじるタブとデザインをいじるタブに分かれてるのがいいですね。内容を考えるときは内容に集中でき,あとでデザインを考えればいいわけです。

最初にタイトルを入力したら,内容部分に入っていきます。見出し,テキスト,画像,のようなものが選べます。上記のマニュアル的なものを作ったときは,「PCでのやり方」と「スマホでのやり方」という見出しをつけて,その下にどんどん画像を貼り付けてキャプションをつけただけでした。

画像はCCで使えるものを検索してくれたり,YouTubeの動画を検索して挿入することもできます。ウェブベースなので共有して共同作業も楽にできますし,もちろん編集権限は与えずにリンクを共有すれば学生に見てもらう資料としても活用できます。

簡単な機能しか使ってみてないのですが,デバイスで閲覧すること前提の資料はもうこれで良いのではないかという気はしています。一応印刷もできますし,MS WordやPDF形式でのエクスポートもできるので,紙媒体で印刷して配布という場合にも対応はできそうです。ただ,もし最初から印刷前提であれば,履歴書,ニュースレター等のテンプレもありますのでそちらを使ったほうが印刷したときの見栄えがよくなるかもしれませんね。

おわりに

今回の記事では,MicrosoftのSwayというアプリを紹介しました。今の状況って,次から次へと新しいツールの紹介が流れてきて,結構食傷気味になったりすることもあるんですが,少なくとも僕がちょっとSwayを触ってみた感じだと,かなり直感的に資料を作れたので,WordやPPTよりよっぽど簡単にできるなと思いました。もちろん,細かいところ,かゆいところに手が届かないというのは凝ったことしようとしたら出てくるでしょうけれども,シンプルでいいという場合にはSwayで十分なんじゃないかなと思います。

なにをゆう たむらゆう。

おしまい。

Wunderlistがついに終了する

むかしむかし,大学院生のときに,タスク管理のためにTo doリストを使い始めました。使い始めたときには,使用感をまた記事に書きますねとか言ってたんですが,その記事が書かれないままついにWunderlistがサービスを終了してしまうことになりました。

過去記事:遠くからライフルで撃つか,接近戦でナイフで仕留めるか。

終了するという話は随分前からされていたのですが,まだ別に先の話(実際に5月までは使えますしね)だということで全然乗り換えとかも考えていませんでした。それが,Wunderlistにブラウザ上でログインするとトップ画面に常に早くMicrosoft To Do(MTD)に移行してねっていうメッセージが表示されるようになり,いよいよ本格的に移行を検討しないといけなくなりました。この話題についてGoogleで探してみてヒットした記事は例えば以下のようなもの。

Microsoftが新しいToDoアプリ「To Do」を発表、Wunderlistからの乗り換えを促す

Wunderlist の移行先の検討と移行

Wunderlistがいよいよ終了することに…

Wunderlistの使い方としては昔とそんなに変わっていません。ただ,今のWunderlistは5年前に記事を書いたときと仕様が変わって,フォルダという階層ができました。これが一番上にあって,その下にリストがあって,そのリストの中に個々のタスクを入れていくというようになっています。この階層性を個人的には気に入っています。今は,

  • 研究
  • 仕事
  • プライベート

のようなフォルダを作っていて,研究というフォルダの中に個々の研究プロジェクトのリストがあり,仕事の中に,「授業」,「学内業務」,「学会業務」,「査読」,みたいなリストを入れています。プライベートの中には自分にだけ関わるリスト(G大阪のチケット先行発売日の情報とか)と,妻と共有している買い物リストがあります。

リストの中にいれる個々のタスクには期限日の設定,リマインダの設定,繰り返しの設定,サブタスクの追加ができます。繰り返しの設定があることで,例えば授業の準備のように毎週発生するタスクは一度入れておけば毎週リストに入ります。また,いらない人もいるかと思いますが個人的にはサブタスクが追加できるというのも気に入っている点です。例えば授業準備の中で,リスニングの小テストを作るというタスクがあったとしますよね。そうすると,(a)リスニングの音源を準備する,(b)解答用紙の準備をする,(c)解答用紙を印刷する,のようなサブタスクに分割できるわけです。1度の作業で(a)~(c)の3つすべてを完了できればサブタスクの設定も必要ありませんが,細切れの時間で作業しなくてはいけないことも多いので,サブタスクが設定されていることで,完了までに必要な作業がなにかを瞬時に把握することができます。また,サブタスクを考えるようにすることで,タスク完了までのステップを言語化する必要が生じ,そのことが実際の作業を明確にしてくれるためにタスクを完了するハードルが下がるという効果もあると思っています。こういったサブタスクを普通のタスクとして登録してしまうと,タスクが増えすぎる上に個々のタスクのつながりも見えなくなってしまいますし,リストの数をかなり増やさないといけなくなってしまうので逆に不便です(授業科目ごとにリストを作るとかは別にしたくないし必要性を感じていません)。

今のところ,このように私が必要としているto doリストの機能はMTDにもあるようですし,UIもWunderlistと同じように作られているので,MTDに乗り換えても特に問題は生じないかなと考えています。WunderlistのデータをそのままMTDにインポートすることも可能なようですし。ただ,1つだけ問題があるのは,Googleカレンダーへの同期ができないことです。WunderlistではできるけどMTDではできないことの中で,これはかなり問題が大きくて,実際にMTDのフォーラムでも多くの人がこの機能を熱望していることがわかります。

https://todo.uservoice.com/forums/597175-feature-suggestions/suggestions/32976505-make-microsoft-to-do-with-google-calendar-s-tasks

この連携がないとそこまで困るかというと,タスクの管理に関わる根本的な機能の中では個人的にはサブタスクの設定だったりフォルダ分け(MTDではグループ分け)みたいなものよりは重要度は低いのですが,やっぱりカレンダー見たときにタスクの期限日が一覧で見れるというのは欲しい機能ですよね。

あともう一つの問題は,妻と共有しているリストもあるので私が移行するタイミングで妻にもMTDへ移行してもらわないといけないというところですね。これもちょっと移行をためらう理由ではあります。使えなくなるからしょうがないとはいえ,私は人に何かを頼むという行為のハードルが人より異常に高くて非常に苦手なもので…

というわけで,今日はタスク管理のWunderlistを結構気に入ってたけど,MTDに移行しなければいけなくなってしまいましたというお話でした。

なにをゆう たむらゆう。

おしまい。

vlookup関数で参照先が複数ある時

春学期の成績つける際に書いてあって放置してあった完全に自分用メモです。

成績をつける際に,vlookup関数で名前やIDを参照するというのはよくある作業だと思います。vlookup関数の引数の基本は以下の通り。

vlookup(参照元,範囲,引っ張ってくる列,参照方法)

で,名前の列が1列ならこれだけでいいのですが,スピーキング授業の話の記事で紹介したようにペアでスピーキングテストなんかをやると,得点の列は1列で,名前の列が2列になります。最終的な成績が入るExcelシートでは名前は1列で,vlookup関数は指定範囲の1列目から名前を探してくることになりますから,2列目にある名前は参照されません。そして,誰が1列目で誰が2列目かはわからない状態なので,人によって参照範囲を変えることもできません。そこで使うのがIFERROR関数です。

IFERROR関数は,1つ目の引数でエラーが出た場合に2つ目の引数を実行するという関数です。つまり,この関数の1つ目でペアの1列目から始まる範囲を指定し,2つ目の関数でペアの2列目から始まる範囲を指定すれば解決するというわけです。意外に簡単でした。つまり,

IFERROR(VLOOKUP(名前セル, 参照先1, 引っ張ってくる列, 参照方法), VLOOKUP(名前セル, 参照先2, 引っ張ってくる列, 参照方法))

とすれば良いことになります。参照先1では2列あるペア列の1列目が先頭列になるように指定し,参照先2では2列目が先頭列になるように1列参照列を右側にずらします。そして,引っ張ってくる列も1列ずらして指定します。こうすることで,1列目の中から名前を探して点数を引っ張ってきて,もしここでエラーが出る(つまり1列目に名前がない)場合には2列目の中から名前を探して対応する点数を引っ張ってくることになります。このやり方を応用すれば,ペアだけではなく3人や4人といったグループの場合でも同じことができます。もちろん,Rとかで縦横変換して名前の列はすべて1列にまとめるようなことをしても最終的に名前が1列,点数で1列という形のデータを得ることはできるのですが。今回はEXCEL上で完結させる場合の話でした。

なにをゆう たむらゆう。

おしまい。

 

[R] Rmarkdown(xaringan)で学会発表スライド作るときの超初心者メモ

ちょっと放置してあったので一部思い出しながらですがメモ書きです。もう一ヶ月も前になりますが,発表資料をRmarkdownで作って公開するということをしました。これまでならkeynoteで作ってPDFにしてslideshareやspeakerdeckにしてたのですが,分析が結構モリモリでこの部分はすでにRmarkdownで作ってあったので,その部分をベースにして他のスライドを作ってしまうほうが早いと思ってすべてRmarkdownでいくことにしました(結果的にそれで時間が余計にかかった気も笑)。

Rの講習的なものや、論文投稿時に実験データの分析レポートを添えて出す、という時以外でRmarkdownを使う機会が今までなく、学会発表スライドを作るときにいくつかつまずくポイントがあったので、今後同じことにならないように自分用のメモとして残しておきます。基本的なこともきっと含まれていると思うので、本当に初心者向けです。ちなみに、私が使っているのはオンラインプレビューができるxaringanというやつです。

  1. R chunkオプションでcache =T
  2. 画像を2枚並べて表示する
  3. 画像の埋め込みに注意

Cache = Tオプション

分析の結果を提示する際に、R上で分析したものをそのままスライドに埋め込める(いちいち表にまとめ直してパワポに貼り付けるとかの必要がない)というのがRmarkdownの強みですよね。しかし、中には1つの分析にかなりの時間がかかる場合もあります。その分析コードの部分以外のところを修正したりしてknitすると、分析に時間がかかるので修正したかった部分が反映されたのかとかを見るのにも無駄な時間を費やしてしまいます。特に、xaringanはRmdを保存したら自動的にknitするので、こまめに保存しながらやる癖がついていたらなおさら大変です。分析が1度だけならまだしも、いくつも分析がある場合には数時間とかかかることもあるかもしれません。ベイズとかだったらもっとですよね。

で、これを回避するために、分析コードのRチャンクのオプションとしてcache =Tというのがあります。これをすることで、一度knitして分析をすれば、その計算結果を保存しておいてくれます。よって、分析をいちいちし直すことをしないので時間もかかりません。注意点は,この分析コードのあるチャンク内での変更があった場合と、この分析コードのチャンクオプションに変更があった場合にはもう一度分析をやり直すということです。よって,時間を要する分析のコードは最初にcache =Tにして一度knitしてしまい,細かいところをいじるのは後にするというのがいいのかなと思います。

画像を並べて表示

普通にRで描くプロットを並べて出すには,par(mfrow=(c1,2))みたいにしてあげれば1行2列でできますよね。で,xaringanでこれやってもどうしても2枚横並びの表示になりませんでした。そこで色々調べたところ,出力の際の幅を半分にしてあげればよいというアドバイスを見かけたので,Rチャンクオプションでout.width =”50%”としてあげました。画像の解像度はdpiオプションで調整できるので,この2つの組み合わせでいい感じに仕上げてあげればよいのかなと。

画像の埋め込み

これがxaringan使うときのネックになるポイントなのですが,xaringanは画像ファイルなどがself-containedではないんですよね。よって,ウェブ上にスライドを公開しようとしたときにHTMLファイルだけアップロードすればよいというわけにはいきません。GitHubなどに画像ファイルなどもすべてアップロードする必要がありました。もしかすると何か方法があるのかもしれませんが,結局ウェブにアップロードするしか解決策が見つからなかったのでこういう方法にしました。xaringanはオンラインでプレビューできるという点が強みなのですが,アップロードとかにちょっと手間がかかるというのが難点かもしれません。また,画像ファイルもアップロードすることでオンライン上での閲覧は問題なくなりますが,DLすると見た目が変わる&画像が見れないということになるので,他の媒体でPDF公開されているスライドをDLしてオフライン環境で見ることが多いというような方々にとっては,普通にPDFで公開してくれよめんどいなぁということになってしまうのかもしれません。非常に悩ましいです。

おわりに

私自身GitHub初心者なので,毎回やるたびにどうやってやるのかいちいち調べながらやっていて,もしかすると普通のプレゼンソフトでスライド作ったほうが時間かからないんじゃないか…とか思いつつ,無駄なこだわりでRmarkdownを使って投影資料を作るようにしています。他にもいくつかつまづいたポイントがあったような記憶があるのですが,いかんせんもう覚えていないのでとりあえず上記3点だけメモとして残しておきます。R関係については意外と自分が一番助かっているのではないかと思うくらい自分でよく忘れて記事探すことが多いので,これもきっと未来の自分を助けることになると信じて。そして,こうやって書いて公開すると解決策が見つかったりするかもしれないという淡い期待を抱いて….

なにをゆう たむらゆう。

おしまい。

Slackを用いた授業外ライティング活動の便利ワザ[Google Spreadsheet編③]

はじめに

下記の2つの記事の続きで,おまけ的なものですが自分の備忘録のためにも残しておきます(R編がなかなかスタートしないw)。

Slackを用いた授業外ライティング活動の便利ワザ [Google Spreadsheet編①]

Slackを用いた授業外ライティング活動の便利ワザ[Google Spreadsheet編②]

簡単に何をやっているのかをまとめます。Slack上で授業外ライティング活動をさせ,そこで書かれたものをGoogle Apps Scriptを使ってGoogle Spreadsheetに記録し,そこで個人の1週間あたりの産出語数を学生と共有するということをやっています。大まかな枠組みについては,上記の記事でカバーされていますが,今回は,「ちょっとかゆいところに手が届くといいな」くらいのお話です。

問題の所在

https://twitter.com/tam07pb915/status/1118157873219948545

学生の書いたものを読んでいると,カンマやピリオドの後に半角スペースを入れないで書いているものが頻繁にありました。

Yesterday,I went to the zoo with my family.After that,we went to an Italian restaurant.It was delicious.

みたいな感じのものを想像していただければいいかなと思います。見る人が見たら気持ち悪くてたまらないと思うのですが,おそらくデジタル環境で英語を書くという経験の少なさからこのような英文になってしまうのだと思います。もちろん,タイポのようなことはありうるのですが,それでも一つの投稿で頻発していたり,ある特定の学習者が連続して誤りを犯しているとどうもこれは半角スペースを入れることを知らないのではないか?と考えるようになりました。

手書きでスペースをあける行為と,キーボードやスマートフォン上でスペースバーを押したり,フリック入力時に「空白」と書かれた部分をタップしたりという行為が関連付けられていないのかもしれません。また,日本語では句読点の後にスペースを入れるというルールはありません。

だからといって,彼らの今後の英語使用場面として手書き以外で英語を書くことがないと想定することはできませんし、スペース入れるということも身につけて欲しい(そうじゃない文見たときの気持ち悪さもわかって欲しい)ことではあるのでしつこく言っていかないといけない気がしています。もちろん,気づいたときにはメインのチャンネルにも共有する形でスペースを入れるようにコメントを出してもいます。ただ,そういうことよりもむしろ「リアルなコミュニケーション」の道具として英語を使って教員ともやりとりしてほしいというところもありますので,あまり半角スペース警察にはなりたくありません。

また,授業運営上でも問題はあります。それは,語数のカウントです。語数のカウントは,1語ずつを単語だと認識して数え上げているわけではなく,単語と単語の間に生まれるスペースを基準にして数えています(詳細は上記の過去記事か,「エクセル 単語数える」とかでググって見てください)。つまり,”Yesterday, I”は2語と認識されても,”Yesterday,I”は1語になってしまうというわけです。ピリオドのあとに半角スペースがなく次の文が始まる場合も同様です。私は,「1週間で○○語を書き込むこと」を課題としていますので,あまりにもこのミスが多いと語数のカウントが通常より少なく計算されてしまいます。

解決方法

私が考えつく解決方法は以下のとおりです。一番土方っぽいものから順に,

  1. Googlespreadsheetの書き込みを1セルずつ確認して,ピリオドやカンマのあとにスペースがなければ手作業で足す
  2. Googlespreadsheetの「検索と置換」でピリオドやカンマを探し,ヒットしたものを目視で確認して半角スペースがなければ足す
  3. Googlespreadsheetの「検索と置換」で正規表現を使ってピリオドやカンマのあとにスペースがないものを一括で修正する
  4. Googlespreadsheetでsubstitute関数を使って置換する

1や2はありえないとして,3も問題があります。それは定期的に作業をしないといけないという点です。Googlespreadsheetを使う利点は,一度作業をしたらしばらくの間は放置しておいても勝手に語数が記録されて学生が確認できるという点です。したがって,できれば4で考えたいところです。しかしながら問題は,substitute関数では置換したい対象をうまく持ってこれないという点です。もしも,「すべてのカンマまたはピリオドについて,ピリオドまたはカンマと半角スペースに入れ替える」とすると,正しく使われているところに余計にスペースを入れてしまうことになります。そうなると,スペースの数を基準とする語数カウントがうまくいきません。そこで,正規表現を使う必要が出てきます。なんと,Googlespraedsheetには正規表現が使える次のような関数があります。

  • REGEXEXTRACT(正規表現で一致する文字列を抽出)
  • REGEXMATCH(正規表現で一致する文字列があるか検索して真偽値を返す)
  • REGEXREPLACE(正規表現で一致する文字列を別の文字列に置き換える)

今回の場合は,置き換えが必要なので3番目のREGEXREPLACE関数を使います。正規表現についての詳しい説明はウェブ上にごろごろ転がっているので,以下では詳しい説明はしませんのでご了承ください(注1)。REGEXREPLACE関数は,REGEXREPLACE(検索対象テキスト, 正規表現, 置換)という引数を取ります。最初の検索対象は学生が書き込んだテキストの入っているセルをしていすることになります。では,正規表現の部分はどうすればよいでしょうか。置換したい対象の文字列は,「ピリオドまたはカンマのあとに単語列が続くもの」でした。これを正規表現で表すと次のようにできます。

“(\.|\,)(\w+)”

ここで,カッコでくくってグループ化しているのは,置換するときに元の文字列を使いたいからです。置換は,ピリオドとカンマ,その後に続く単語列はそのままで間にスペースを挟むので,

“$1 $2”

$1は最初にグループ化したものなので,ピリオドまたはカンマ,$2は次にグループ化したものなので,任意の単語列になります。その間に半角スペースが入っています。つまり,次のような関数が完成形になります。

=regexreplace(テキストのあるセル, “(\.|\,)(\w+)”, “$1 $2”)

これで,ピリオドまたはカンマのあとに単語列が続くときは半角スペースを挟む」という作業ができるようになりました。あとは,この関数のセルに対して語数カウントをする数式を適用すればよいわけです。

新たな問題

さて,うまくいったかのようにみえたのですが,実は先程の例を使うと別の問題が発生することに気づきました。それは,半角スペースはあるけれど,それがピリオドやカンマの前にあるという場合でした。例えば,下記のようなものです。

Yesterday ,I went to the zoo with my family .After that ,we went to an Italian restaurant .It was delicious.

このような用例に対して先程のREGEXREPLACE関数を適用してしまうと,新しく得られるものは次のようになります。

Yesterday , I went to the zoo with my family . After that, we went to an Italian restaurant . It was delicious.

これでは,カンマやピリオドが1つの単語として認識されてしまい,語数のカウントが逆に多くなってしまいます。これを避けるには,「文字列の直後にあるカンマやピリオドの場合には」という条件を加えれば良さそうです(注2)。ということで,改良版は次のようなものです。

=regrexreplace(テキストのあるセル, “(\w+)(\.|\,)(\w+)”, “$1$2 $3”

Googlespreadsheet上で見ると下記画像のようになります。

置換前と置換後のテキストと,それぞれの語数カウントの比較

 

おまけ(絵文字タグの削除)

slackといえば,絵文字も使えます。絵文字も文字コミュニケーションにおいては重要だという部分もありますし,一切絵文字は使うなというのもおかしな話です。slackから書き出される絵文字は,半角のコロン(:)に挟まれたタグになってテキスト化されます。”:heart:”や”rolling_on_the_floor_laughing”と言った感じです。これが文字列にくっついている場合は特に問題ありません(注3)。しかし,文字列から独立した状態で使われると,絵文字1つが1単語と認識されてしまいます。このことに気づくと,すべての文に絵文字をつけたり,あるいは半角スペースを挟んで絵文字を連続させたりという学生が現れます。昨年度は口頭注意でそれなりにケアしていましたが,どうせREGEXREPLACE関数を使うのだから,絵文字タグも取ってしまえばいいということに気づきました。下記のようにしてあげると,絵文字タグが取れます(注4)。

=regexreplace(テキストのあるセル,“\:.*?\:”,“”)

実際にGooglespreadsheet上で使うときには,スペースが入っていないことで生じる問題を解決する関数を使った上で,その結果の出力に対してさらに別の列で絵文字タグを取る関数を使うのもありです。むしろ,プログラミング的には良いのだと思います。なぜなら,なにか問題があったときにその問題の原因を探りやすいからです。ただ,入れ子にすれば1列で済みます。

=regexreplace(regexreplace(テキストのあるセル,“\:.*?\:”,“”),“(\w+)(\.|\,)(\w+)”,“$1$2 $3”)

さらに,語数をカウントする数式にこのREGEXREPLACE関数も入れ込むと…

=(LEN(regexreplace(regexreplace(テキストのあるセル,“\:.*?\:”,“”),“(\w+)(\.|\,)(\w+)”,“$1$2 $3”))LEN(SUBSTITUTE(regexreplace(regexreplace(テキストのあるセル,“\:.*?\:”,“”),“(\w+)(\.|\,)(\w+)”,“$1$2 $3”),” “,“”)))+1

もうなんだかわけがわからなくなってきましたが,この最後の数式を使えば,新しく列を増やしたりすることなしに語数カウントができるようになっています。

おわりに

この記事では,Googlespreadsheetで正規表現を使って学習者が犯すパンクチュエーションの誤りを直すということの例を示しました。他の媒体(R,Python,サクラエディタ)等で正規表現を使った経験があるのでなんとかなりました。一応ざっと確認して特に問題ないとは思っていますが,正規表現にはあまり自信がないので間違いを見つけた方はどうかコメント欄等でご指摘ください。

なにをゆう たむらゆう。

おしまい。

注1: 記号類をそのまま使うときになんでもかんでもエスケープ記号つけるのは私の癖です(そして一貫性もないですたまに忘れるので)

注2: この方法の一つの問題は,”I ate lunch ,and took a nap.”のようなものが残ってしまうという点です。「半角スペースの直後にピリオドやカンマがあり,その直後に文字列が続く場合には,半角スペースを消して文字列とピリオドやカンマの後に挿入する」のようにすれば解決されます。ただし,関数の入れ子が複雑になる上に単語数カウントには関係ないので今回は無視しています。REGEXREPLACE関数でやるとすれば,次のようなものになるかなと思います。

=regexreplace(対象文字列のセル,“\s(\.|\,)(\w+)”,“$1 $2”)

注3: もしも,単語リストを作ったり,コロケーションを見たりのようにテキスト分析にいこうとすると,この絵文字タグは外してあげないと絵文字タグと隣接する文字列が認識されなくなってしまいます。

注4: 17:10:29のように時間をコロン区切りで書き込むような例があると,これも引っかかってしまうのですが,まあほとんどないと言っていいと思うので木にしていません。

Rmarkdownでスライド作るときのリアルタイムプレビュー

Twitterでたまたま見つけてすごく便利そうだったので試してみたら本当に便利だったという話です。元ネタは下記のリンク。自分用のメモとしても残しておきます。

Instant preview without fully rebuilding HTML, and the linked navigation

RmarkdownはRスクリプト書くだけじゃなくてスライド作りができて,Rのスクリプトやその結果も出力に混ぜたりできるので便利なのですが,1つの難点が,実際の出力がその場で確認できないということなのですね。つまり,Rmdファイルで書いているものがスライドにどう落とし込まれるのかについては,knitしてHTMLファイルを作らないとわからないと。で,それはめんどくさいので,編集しながらリアルタイムプレビューが見れるようにしたよというのが上のリンク先の話です。xaringanパッケージというものを使います。xaringanパッケージをつかったスライド作成については他に詳しく書かれている方もいるのでそちらのリンクを。

xaringanによるスライド作成入門

もともと,xaringanパッケージのInfinite Moon Readerというものは,編集中の.Rmdファイルをsaveしたらプレビューが見れるというもので,それを拡張してわざわざsaveせずともプレビューが見れるようにしたというものです。デモのスクリーンキャプチャ動画を載せておきます。

上のリンク先にも書いてありますが,Rのコードチャンクはリアルタイムでは反映されないので,一旦saveしてコンパイルし直す必要があります。

outputオプションがxaringan::moon_readerになっていないとこのプレビュー機能は使えないので,デザインが気に入らないという人はcssファイルをいじって自分好みに変更するということをしなくてはいけないようです。詳しくは,上の「スライド作成入門」のリンクを御覧ください。私は日本語フォントが中国語っぽくなってしまってうのを避けるために,フォントの設定だけいじりました。slides_filesの下にあるremark-css-0.0.1に,”default-fonts.css”というファイルがあるので,それをコピペしてRmdファイルが有る場所と同じディレクトリに”My-font.css”というファイルをつくりました。その中で,”body{ font-family:”の後ろに自分の好きなフォントを書いて保存すればOKです(下記の画像参照)。

他には,スライドのフォントサイズを変えるというのもしたかったので,下記のリンクを参考にしました。フォントを変えるのと同様に,”default.css”をコピペして”My-theme.css”というファイルを作り,そこにスライド全体のフォントサイズを変える設定を追記しました。また,リンク先にスライドの1ページだけフォントサイズを変える”.my-one-page-font”というのもあったのでそれも追記しました。

https://stackoverflow.com/questions/53481699/customize-font-size-for-all-the-slides-in-xaringan

それから,スライドの中で一部分だけ文字サイズを小さくしたり大きくしたりというのもタグでできると便利なので,下記のリンク先で書かれていた”.small”と”.large”というのも”My-theme.css”に追記しています。

https://github.com/yihui/xaringan/wiki/Font-Size

これらの自分好み設定を反映させるには,YAMLヘッダーのoutputオプションを次のようにしてあげます。

output:
xaringan::moon_reader:
css: [“My-theme.css”,”My-font.css”]

Rmarkdownでスライド作ることに慣れている人や,がつがつcssファイル書いてカスタマイズできる人には当たり前のことかもしれないのですが,私はそのあたり初心者なのでこういうことも知りませんでした。

ちなみにですが,このxaringan::moon_readerにはめちゃくちゃ面白い“yolo: true”というオプションがあります。

 

ちなみに,これは挿入される画像を自分で指定することもできますし,どのくらいの頻度かも指定できます。こういう遊び心があるのはなんかいいですよね。

というわけで,Rmarkdownでスライドを作ったりする方はぜひ一度お試しあれ。

なにをゆう たむらゆう。

おしまい。

 

[R] 同じディレクトリ内でファイルを複製する

はじめに

ライティングの授業で(またそれかよ),次のようなことを考えました。

テンプレートのファイルを作って,学生の人数分だけコピーし,さらにそれぞれのファイルに学生の名前をつけたい!

まず思いつくのは,雛形ファイルを作り,Ctrl+CとCtrl+Vを駆使して学生の人数分のファイルを用意し,1つずつファイルをリネームするといういわゆる土方作業ですが,そんなことやってられませんよね。というわけで,Rで簡単にファイル複製とリネームをやってしまおうということです。別に特別なことはしておらず,自分用のメモです。もっと簡単な方法があれば教えてください。

ワーキングディレクトリを変更

まず,ワーキングディレクトリを,テンプレファイルが置いてある場所に変更しましょう。

setwd("C:/Users/Yu/Desktop/test")

getwd()

## [1] "C:/Users/Yu/Desktop/test"

必要な情報を取得

ファイルをコピーする際にフルパスを使うので,その情報をあらかじめ変数に入れておきます。そして,list.files()関数で,ワーキングディレクトリ内にあるファイルの情報を取得します(別に1つしかないので手入力でもOKです)。そして,originalという変数に,テンプレファイルのフルパスを入れておきます。

dirnow<-getwd()

file<-list.files()
original<-file.path(dirnow,file)


ファイル名の準備

ファイルにつける名前の準備です。ここでは例としてアルファベットを使っていますが,学生の名前を使う場合は学生の名前をコピペする等してname変数に入れてください。その後,テンプレファイルの前に名前をつけてfilenameという変数に入れています。sep=”_”は区切り文字をアンダーバーで指定しているということなので,ここは任意の文字に変えられます。

name<-LETTERS[1:26]
filename<-paste(name,"test.docx",sep="_")

print(filename)

##  [1] "A_test.docx" "B_test.docx" "C_test.docx" "D_test.docx" "E_test.docx"
##  [6] "F_test.docx" "G_test.docx" "H_test.docx" "I_test.docx" "J_test.docx"
## [11] "K_test.docx" "L_test.docx" "M_test.docx" "N_test.docx" "O_test.docx"
## [16] "P_test.docx" "Q_test.docx" "R_test.docx" "S_test.docx" "T_test.docx"
## [21] "U_test.docx" "V_test.docx" "W_test.docx" "X_test.docx" "Y_test.docx"
## [26] "Z_test.docx"

ファイルのコピーとリネーム

それでは,ここで,ファイルのコピーとファイルの名前変更をfor関数で一気に行います。file.copy()関数は,fromでコピー元,toでコピー先を指定します。この時,fromではもとファイルのフルパスであるoriginalを使います。そして,toのところで,「ワーキングディレクトリ+名前変更後のファイル名」を指定してあげると,コピーされたファイル名に名前がつくことになります。paste()関数は,文字列結合の関数です。ファイルの一覧の中にblog.htmlとblog.Rmdというファイルが入っていますが,この2つはこのブログのために作ったファイルですので関係ないです。

for (i in 1:length(filename)){
file.copy(from=original,to=paste(dirnow,filename[i],sep="/"))
}

list.files()

##  [1] "A_test.docx"     "B_test.docx"     "blog.html"      
##  [4] "blog.Rmd"        "C_test.docx"     "D_test.docx"    
##  [7] "E_test.docx"     "F_test.docx"     "G_test.docx"    
## [10] "H_test.docx"     "I_test.docx"     "J_test.docx"    
## [13] "K_test.docx"     "L_test.docx"     "M_test.docx"    
## [16] "N_test.docx"     "O_test.docx"     "P_test.docx"    
## [19] "Q_test.docx"     "R_test.docx"     "S_test.docx"    
## [22] "T_test.docx"     "test.docx"       "test.Rproj"     
## [25] "U_test.docx"     "V_test.docx"     "W_test.docx"    
## [28] "X_test.docx"     "Y_test.docx"     "Z_test.docx"

こんな感じでファイル複製とリネームができます。Google Classroomを使っていると、教材ファイルをコピーして配布という機能があり、それを使うと自動的に学生の名前のついたファイルができるのですが,それなしでやろうとすると,こうなるかなという感じです。

これを使って何をするかという記事はまた改めてポストしようと思います。

なにをゆう たむらゆう。

おしまい。

Slackを用いた授業外ライティング活動の便利ワザ[Google Spreadsheet編②]

はじめに

下記の前回の記事の続きです。

Slackを用いた授業外ライティング活動の便利ワザ [Google Spreadsheet編①]

前回の記事では,Google Apps Script (GAS)を利用して,Slackに書き込まれた内容をGoogle Spreadsheetに記録し,その記録をもとに語数を数えるという話でした。この記事では,それをもう少し便利にするために,「ある特定の期間で区切って語数をカウントする」というお話です。例えば,1日ごと,1週間ごとみたいな。月ごとの場合は,前回の記事で紹介した方法は月ごとに新しいspreadsheetのファイルができるので楽なんですが,「同じファイル内のシートの中で一定の期間の間ごとに区切りたい」となると,少しだけ工夫がいります。といっても,spreadsheet内で関数を書くだけなのでそんなに大変なことではありません。一度雛形ができればあとはコピペして少し書き換えるだけですみます。

前回のおさらい

少しだけ前回の記事に書いた内容に触れておきます。GASを使ってspreadsheetに取り込まれた状態は,下記画像のようになっています。

Screen Shot 2018-09-24 at 22.50.58

A列が日付,B列が名前,C列が書き込まれたテキスト,D列がもとのJSON形式の情報です。このシートが,チャンネルの数だけ一つのファイルにある状態です。前回は,GASで更新されるこのシートの情報を以下のような手順に沿って使いました。

  1. importrange関数を使って別のファイルにエクスポート
  2. そのシートに語数をカウントするE列を挿入
  3. sumproduct関数で名前列を参照してE列の合計を求める

すると,下記画像のようなまとめシートができます。

sumproduct-example

今回は,そこに「日付の情報も参照する」という情報も付け加えていくことになります。

同じ月内で1週間ごとに語数を数える

では,実際に私がやっている実践に即して,1週間ごとに語数を数えるという作業をやる方法です。先程説明したように,前提は一ヶ月で一つのファイルができ,そのファイルの中にチャンネルの数だけシートがあるという状態です。同じ月内であれば一つのシートの情報で,以下のような作業をspreadsheetにやってもらいます(注1)。

  1. まとめシートのA列にあるセルの名前に当てはまるものだけをフィルタリング
  2. 参照元シートのB列にある日付の情報を参照し,指定した1週間のものだけをフィルタリング
  3. 1と2で絞り込まれたデータのE列の語数を合計して計算する

注意点は,参照するデータのシートでは名前がB列,日付がA列なのに,まとめシートでは名前はA列になっているという点です。どの列にどのデータがあり,どこの列を参照するのかを考えないと混乱するかもしれません。さて,前回はsumproduct関数使ったんですが,今回使うsumifs関数でも同じことが可能だと思うので,全部sumifs関数でやってもいいかもしれません。

先にあとで説明する作業が完了した状態のシートの画像を見てください。1つ前の画像の状態から,下記の画像の状態にすることが今回の目標です(注2)。

Screen Shot 2018-10-12 at 14.12.11

私がこのSlackライティング活動を採用しているのは金曜日の授業で,金曜日から次の週の木曜日までを1週間としています。日付で区切っていて時間で区切っているわけではないので,今回は日付で絞り込みにしています(午後5時までとかそういう切り方だと時間も指定する必要があります)。

では,上の画像のB2の列にはどのような式が入力されているのか見てみましょう。

Screen Shot 2018-10-12 at 14.12.38

画像中の式で最後に”-5″しているのは,最初は必ず”@XXX has joined the channel. “という5語の文が記録されているので,それを排除するためです。

sumifs関数の基本的な引数はsumifs(合計範囲, 条件範囲1, 条件1, 条件範囲2, 条件2, …)のようになっています。合計範囲とは,合計を計算したい範囲のことですので,今回の場合はE列の語数の列を選択します。”Friday2_201809″というのが,金曜2限クラスの9月分のデータがエクスポートされたシートになります。このまとめシートはimportrangeで自動的にデータがエクスポートされるように設定しているspreadsheetファイルの中に作っているので,”Friday2_201809!$E$1:$E$1000″で,「9月分のデータのE列(語数列)」を合計範囲として指定していることになります。コピーしたときに範囲が変わることを防ぐために,絶対参照にしています。

2つ目の引数は,同じ”Friday2_201809″のA列を1つ目の条件範囲にしています。A列は日付の入っている列ですから,日付列を条件範囲としていることになります。そして,3つめの引数で日付の条件指定を行います。最初の1週間は,もともとデータ記録の一番最初(2018年9月21日)が1週間の1日目でしたので,7日目(終わりの日)だけを指定しています。これには等号・不等号の使い方でいろいろなやり方が考えられますので,この例は一例です。

“<“&”2018-09-28”

等号・不等号は必ずそれのみをクォーテーションマークでくくり,クォーテーションマークでくくった日付と&でつなぐようにします。上の式が意味しているのは,「2018年9月28日より前(つまり27日以前)」です。これで,9月28日0時00分以降の書き込みが排除されます。

4つ目の引数は条件範囲2です。”Friday2_201809″のB列を参照しています。B列は名前の入った列ですので,名前の絞り込みをしようというわけです。最後の引数は$A2です。「条件範囲2(元データの名前列)の中で,まとめシートのA2セルの名前に当てはまるものだけをフィルタリングしてね」ということです。指定する順番自体は前後していますが,上にも挙げた以下の3つの作業が1つの関数で実現されたことになります。

  1. まとめシートのA列にあるセルの名前に当てはまるものだけをフィルタリング
  2. 元ファイルのB列にある日付の情報を参照し,指定した1週間のものだけをフィルタリング
  3. 1と2で絞り込まれたデータのE列の語数を合計して計算する

これであとは,列を横に足して,別の日付指定をすれば,あとはその条件に当てはまるものだけが自動的に記録されていくことになります。合計範囲指定は固定ですが、条件範囲と条件の指定は名前が先で日付が後でも構いません。

1週間のはじめとおわりを指定する場合

さて,上のやり方は,1週間の終わりだけの指定でしたが,それが使えるのは最初の1度だけで,次からは1週間のはじめの日も指定する必要があります。「○月○日から○月○日まで」としたいわけです。これをやるには,sumifs関数の条件範囲と条件を1つずつ追加すればいいだけです。画像上では順番が前後しますが,下の画像のD列(10/5-10/11)の1週間を指定した場合を見てみましょう。

Screen Shot 2018-10-12 at 14.13.34

1つ目の引数は同じですが,2番目と3番目の引数で始まりの日付の指定,4番目と5番目の引数で終わりの日付の範囲の指定を行っています。

“>=”&”2018-10-05”

という指定は,「2018年10月5日以降」という指定になります。1週間の始まりですね。

“>”&”2018-10-04”

としても同じです。続いて,終わりの日付は,同じように日付列を条件範囲とし,

“<“&”2018-10-12”

を条件にしています。つまり,「2018年10月12日より前」ですので,2018年10月11日の23時59分までのデータが条件に当てはまることになります。

“<=”&”2018-10-11”

でも同じです(むしろこっちのほうがわかりやすいかも)。これで,始まりの日付から終わりの日付までの間の合計語数が計算されます。ここを任意の幅に設定すれば,1週間ではなくとも3日でも4日でも10日でも同じようにできます。

月をまたいだ1週間の語数

同じ月内でのやり方は上の2つのやり方の組み合わせで対応できます。では,月をまたいでしまうときはどうすればよいでしょう。上述したように,月ごとにシートが異なるわけなので,別々のシートに記録された情報を統合する必要が出てきます。ただ,難しいことはなく単純に足し算すればよいだけです。

Screen Shot 2018-10-12 at 14.13.15

この例では,Friday2_201809というシートに9月分,Friday2_201810というシートに,importrange関数でデータを同期させています。9月分のデータで,9月の終わりの数日間(この例では9月28日~9月30日),10月のデータで10月1日からの数日間(この例では10月1日~10月4日)の語数を計算し,合算するという作業です。

つまり,それぞれの月でsumifs関数を使った式を作り,2つのsumifs関数式を+記号でつないであげれば,月をまたいだ場合の語数が計算できます。不等号のみと,不等号+等号の意味の違いは,上で説明したとおりです。

おわりに

ということで,前回の記事で紹介したGASでデータを引っ張る作業,importrange関数でデータを別ファイルにエクスポートする作業と,今回の記事で紹介したsumifs関数で日付指定する3つのパターンを使えば,一定期間の間の語数記録は簡単にできてしまいます。

エクセルが得意な方はすでにお気づきかもしれませんが,実は,1行目に指定する日付を終わりの日付にし,そのセルを日付の範囲指定に利用することもできます。つまり,上の画像で言えば,B1セルに”2018-09-27″,C1セルに”2018-10-04″,D1セルに”2018-10-11″のようにするということです。ただ,見たときに1週間の範囲がわかるほうがいいかなという理由で,そういうやり方はしていません。

ということで,下処理問題は解決されていませんが,だいたいの語数を記録して,学生がいつでも見れるようにするということについては,前回と今回の記事の内容でだいたいカバーできるのではないかなと思います。今の所第三段は予定していませんが,今後もしも「こういう事が必要だなぁ」という事が出てきたら更新するかもしれません。

なにをゆう たむらゆう。

おしまい。

注1. おそらくExcelのピボットテーブルなら,同じ列に当てはまる複数の条件でのフィルタリング可能だと思うので,Excelならピボットテーブルだけでいけると思います。

注2. 画像で一目瞭然ですが,毎週書き続けられている学生と,すでに脱落してしまっている学生が分かれてしまっているのは問題で,これについては何かしらの介入が必要だと思っています。