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

ノート探しの旅(番外編):Notionでインフォメーションギャップタスクの情報をシェアする

はじめに

ノート関係の記事の派生で,Notionを使いだしてから,「あ,これ,英語の授業でインフォメーション・ギャップタスクやるときに役に立つな」と気づいたお話。

インフォメーション・ギャップタスクの情報分割

英語の授業でインフォメーション・ギャップ型のタスクをやるときって,AとBのワークシートにそれぞれの別の情報を載せたりしますよね。それを相手に見せないようにねみたいな感じで。あるいは,ワークシートとは別に,Aの学生だけ,Bの学生だけに別の参照資料みたいなものを渡すとか。

こういうときに,わざわざ紙に印刷しないで,NotionでAの人が参照するページ,Bの人が参照するページを作って,そのページへのリンクをQRコードにしてAとBのワークシートにそれぞれ載せておけば,「ペアの人に見られないように」みたいな制限をつける必要もないんじゃないかな?という気がしたんですよね。実際に,授業でも試してみましたし,授業準備の手間的にも追加の資料を用意したりする必要がないし,ワークシートのスペースを無駄に圧迫する必要もないのでかなり気に入っています。

向いているタスクと向いていないタスク

このNotionの使い方は,タスク中にその「分割された情報」を見ながらタスクをやることが必須の場合(例:間違い探しや描写課題)にはあまり向いていません。向いていないといいうと語弊があるかもしれませんが,「真価」は発揮できないですね。むしろ,タスク中にはオリジナルの情報をできるだけ参照しないようにしてほしいような課題(例:リーディング素材の間の相違点を見つける課題)のときに力を発揮すると思います。

こういう課題って,印刷したものをそれぞれに配って,それを裏返しにさせたり,あるいは情報を学習者が読み取る時間を確保したあとに教師が回収したりして,オリジナルの情報へのアクセスを制限するわけです。

こういう場合に,その分割された情報がスマホ(あるいはその他のデバイス)上で閲覧する前提になっていれば,紙の資料をわざわざ配って回収みたいなことをしなくてもいいわけです。もちろん,タスク中に資料を見ようと思えば見えてしまうわけですが,それは机間巡視しているときにスマホ画面を見ていたりする学習者がいないかどうかを気をつけて観察すればよいだけです。

もう一つのメリットとして,学習者側のメリットもあります。紙の資料で配られていたら,それを処理するために,辞書でわからない単語を調べたりなどの作業が必要になる場合もありますよね。もちろん辞書を引くという行為自体は大事なのですが,単語の意味を調べるために,印刷された情報をデバイスに入力させる必要はあまりないと思います。資料をオンラインで提供していれば,その情報はデバイス上で資料を読めるわけですから,わからない単語を調べたりその発音をチェックしたりみたいなことも,随分やりやすくなります。

おわりに

別にNotionではなくても,例えばWordファイルをDropboxやOneDriveなどのクラウドストレージサービス上において,それの共有リンクを作ってQRコードにすれば同じことなのですが,インフォメーション・ギャップ型のタスクで使うような情報って,別にWordみたいな印刷を前提にしたフォーマットにする必要がないんですよね。だったらもっとシンプルなmarkdownでいいわけです。となると,こういう用途にNotionは活用がかなりできそうだな,ということで,そういう用途で結構使い倒しています。

なにをゆう たむらゆう。

おしまい。

Obsidianで「やったことリスト」をつくる

はじめに

私は何年か前から,「やることリスト」や「To Do List」ではなくて,「やったことリスト」をつけるようにしています。

ToDo(やること)リストじゃなくてDone(やったこと)リストをつけよう

2つの記事のうち下のものは10年以上も前に書かれているので,アイデアとして何か目新しいわけではありません。なんでそれやるの?みたいな話の詳細は上の2つの記事をお読みください。私はとにかく,「なにかやった」ということを日々積み重ねていってそれを可視化したい,というのが大きいです。「いや〜今日は何もできなかった」という日でも,ノートを書くために一日を振り返ってみたら,「仕事をしないぞ。休むぞ。」と決めた日以外には絶対に何かやってるんですよね。「あ,何もやってないと思ったけどなんかやってたわ。」と(自己肯定感下がらない)。「てか意外に結構やってない?」と思う日もありますし。一日にやってる仕事の数が多すぎて,こんなリスト書いてる時間がもったいないよと思っちゃう人もいると思いますけど,そういう人は別にこんなことしなくても自己肯定感下がったりしないと思うし必要のないことなので,関係のない話かなと思います。私みたいに,「ああ,私は仕事のできないダメ人間だ」という気持ち(になったりすることがある)人の参考になる可能性があるかもしれないということでこの記事を書いています。ぜひ試してみてください。

さて,この記事では,Obisidanを使って「やったことリスト」を実現する方法を紹介します。

以前はEvernoteでやっていた

リストをObsidianに移行する前は,Evernoteに一つの「やったことリスト」というノートを作って,そこに毎日日付の見出しを作ってからチェックボックスで消していく(あえてチェックボックスにするのが個人的には重要)というようにしていました。このノートはホーム画面にピン留めしておいて,Evernoteを開けば常に見れるようにしていたというわけです。

Evernoteは値上げをどんどんしていて,Evernote離れしている人も増えていますが,私個人としてはWebクリッパー(この用途では10年以上使っています)や紙関係でスキャンしたものの保存先として多用しているので,利用を辞めることはおそらく今後もないと思います。ただ,研究関係のメモをObsidianに移行してからは,Evernoteを開く機会自体が結構減ったんですよね。結果として,Evernoteを開くのが面倒だからリストを作るのも面倒で,さらには毎日日付を自分で書くのも面倒だなと思い始めてしまったのです。

日付書くの面倒問題以外でも,リストにちょっとしたメモを残したりできたら便利だなと思っていました。次はこういうふうにやり方を変えようとか,これの続きを次にやるときはこっからスタートだよとか。そういう余白みたいなのがないんですよね。一つのノートだと。となると,毎日のノートが独立していたほうがいいんです。最近Evernoteでもデイリーノートが作れるのを知ったので,Evernoteでも解消できるかもしれませんが,研究関係のものが常に目に入るようにするためにもObsidianは常時開くようになっていたので,Obsidian上でやったことリストができないかなと思い,実際にやってみたというわけです。

自分が理想としていたリストの作り方

いろんなやり方があると思いますが,私が思い描いていたのは次のような仕組みです。

  1. ワンクリックでデイリーノートを作れる
  2. デイリーノートにはテンプレとしてタスクリストがすでに記入されている
  3. 毎日のデイリーノートが「やったことリスト」という名前の別のノートに自動的にリンクされる(やったことリストからデイリーノートにジャンプできる)
  4. リンクされるのは「リスト部分」だけで,見出しが日付,その下にリスト,という見え方になる
  5. 新しいリストは常に上に追加される

おそらく,1のところはコアプラグインの起動時にデイリーノートを開くという設定をONにすれば,クリックすらせずにデイリーノートが作れると思います。ただし,私の場合は毎日の日記というよりも「仕事」メインなので,仕事をしない日にはデイリーノートを作る必要がありません。むしろそれで作ってしまうと,デイリーノートがあるのに何もやっていない日が逆に可視化されてしまって本来の目的と逆方向にいってしまうのでよくありません。そういうわけで,ワンクリックする手間を設けています。

必要なプラグイン

  • デイリーノート
  • Dataview

多分最小限でこの2つで可能なはずです。まずはプラグインをインストールしましょう。話はそれからです。

ちなみに,私はなぜかコアプラグインの”デイリーノート”ではなく,”Periodic Notes“というコミュニティプラグインを使っています。なんでそうしたのかはもはや忘れました。WeeklyとかMonthlyとかのノートも作れるので汎用性が高いからかもしれません(まだ毎週,毎月とかでノート作って書いたりしてないですけど)。あ,”Calendar“プラグインとの統合があるからかもしれませんね。カレンダービューで日付をクリックするとその日のデイリーノートに飛んでいけるみたいな。もしかしたらコアプラグインのデイリーノートでもできるのかもしれませんけど。まあそれは今回のメインの部分とはあまり関係ないので割愛します。

それから,”Dataview“これが肝です。これがあることで,日々のデイリーノートを「やったことリスト」に蓄積していくことができます。使い方はめちゃくちゃ汎用性が高くて難しいので,私はChatGPTに聞きながら使いました(もっというと,「Obsidianで,デイリーノートが自動で生成され,そこに作られたタスクビューが自動的に別のノートに蓄積されていくっていう仕組みを作りたいです。」ってChatGPTに質問して教えてもらいながらトライ・アンド・エラーを繰り返して最終的に自分が欲しかった形にたどり着きました)。

余談ですが,ChatGPTに教えてもらったときに,Tasksというプラグインをいれるように言われましたが,実際にはこのプラグイン入れなくてもこの目的で利用する分には何ら問題ありません(このプラグイン自体は便利だと思いますが)。私は締切があるようなタスク管理にはMicrosoftのToDoリストを使っているので。

手順1. テンプレファイルを作る

テンプレファイルを作って,保管庫に置いておきましょう。私は保管庫直下にDailyNote_Template.mdというファイル名で下記画像のようなテンプレファイルを作りました。そして,新しいデイリーノートは”DailyNote”というサブフォルダ内に生成されるようになっています。

同じ名前のファイルがあればそのファイルが開かれるようになっているので,同じ日に複数のファイルを生成してしまうということはありません。やったことはTasksのところに記入していって,メモ的なことはNotesに書くという感じになります。

手順2

デイリーノートが生成されるサブフォルダ内に,「やったことリスト」という名前のノートを作ります(もちろん名前はなんでもいい)。そのノート内に次のように記入してください。”DailyNote”というのはノートを引っ張ってくるフォルダの名前ですので,ご自身の環境に合わせてそこは書き換えてください。

```dataviewjs// ページごとのタスクを格納するための空のオブジェクトを初期化
let tasksByPage = {};

// "DailyNote" フォルダ内のすべてのページを取得し、作成時間の降順でソート
let pages = dv.pages('"DailyNote"')
  .sort(p => p.file.ctime, 'desc');

// 各ページを繰り返し処理し、タスクを抽出
for (let page of pages) {
  let tasks = page.file.tasks;

  // ページにタスクが含まれている場合、未完了タスクと完了タスクに分類
  if (tasks?.length > 0) {
    tasksByPage[page.file.path] = {
      page: page,
      incompleteTasks: tasks.where(t => !t.completed),
      completedTasks: tasks.where(t => t.completed)
    };
  }
}

// tasksByPage オブジェクトの各エントリを繰り返し処理してタスクを表示
for (let path in tasksByPage) {
  let { page, incompleteTasks, completedTasks } = tasksByPage[path];

  // 未完了タスクがある場合、それを表示
  if (incompleteTasks.length > 0) {
    dv.taskList(incompleteTasks, { checked: false });
  }

  // 完了タスクがある場合、それを表示
  if (completedTasks.length > 0) {
    dv.taskList(completedTasks, { checked: true });
  }
}

// タスクが見つからなかった場合、メッセージを表示
if (Object.keys(tasksByPage).length === 0) {
  dv.paragraph("No tasks found in the daily notes.");
}```

色々ChatGPTとあれこれやり取りした結果,DataviewJSというのを使うことになりました(プラグインの設定でDataviewJSが使えるようにしてください)。ぶっちゃけ,このコードに実は余剰な部分とかもあるのかもしれませんが,これで機能しているのでとりあえずいいとしています。「やったことリスト」の出力は下記画像のような見た目になります。

私が結構難儀したのは,最新のノートが上に来るように並び替えることと,見出しをファイル名だけにすることです。見出しにファイル名と日付がダブって入ってしまったりして,かなり何回もChatGPTとやり取りした記憶があります。

ちなみに,完了マークと日付が入っているのと入っていないのがありますが,完了マークと日付が入るのはTasksプラグインの仕様です。このプラグインを使うと予測変換の入力がうまくいかないというのと,項目だけ立ててチェックを忘れてしまったときに,本当はその日のうちにやったのに次の日に終わったようにチェックが入ってしまうというのがあって,他のノートのタスクリストとかでもこのプラグインなくても問題ないよな?とさっき確かめたら問題なさそうだったのでアンインストールした結果,今日の分だけ見え方が変わっています。

もうひとつちなみに,22日の次からノートがスカスカになっているのは,コロナに罹患して仕事どころではなかったからですw

何を「やったこと」に含めるか

私個人的には,研究に限らず仕事の範疇に含まれるものは結構細かいものでも含めています。メール返信とかは一度の返信で済むものだったのでそういう書き方していますが,もし何往復もするようなものだったら,「XXXについてメールでやりとり」というような書き方にしています。論文も,「ただ書いた」だけだとどんくらい書いたとかどこを書いたとかがわからないので,できるだけ具体的にするようにしています。大きなタスクの中にサブタスクがある場合は22日の例のようにインデントしています(実際には論文は書き終わっていないけれども親タスクのところもチェックするのがポイント)。論文とか研究とかはまた別にObsidianの中にまとめのTodoリストがあって,ある研究や論文に固有のノートの中のリストが#ToDo/Researchで拾ってこれるようにしていたりします。そことデイリーノートを連携できていたりはまだしないので,重複した内容をデイリーノートに書くこともあるといえばあります。ただ,そもそもこの「やったことリスト」を作って蓄積していく目的というのは,「なんかやったぞ」もっというと,「何もやってなくないぞ」というのを可視化する目的なので,厳密に「やらないといけないこと」(ToDoリスト)と一致していなくてよいと思っています。むしろ,そういうToDoリストにもぶっちゃけのぼりもしないような細々としたタスクをも可視化するののが目的なんです。

おわりに

この記事では,「やったことリスト」をObisidanのデイリーノートとDataviewを使って蓄積・可視化していくということを書きました。ChatGPTに聞けば,もっと多分いろんなカスタマイズできるんじゃないかと思いますので,詳しいことは私に聞かないでください。

なにをゆう たむらゆう。

おしまい。

[R] 1列だけの選択ならselect関数よりpull関数を使う

はじめに

dplyr使いの方で,select関数を使って特定の1列に対して何かしらの処理をするということをしたいときにエラーが出る人はpull関数を使いましょうという話です。ちなみに,$使えば問題は解決です。今回は,それ以外の方法で,というお話。

具体的になにをしようとしたか

私がどんな処理をしようとしたかについて少し触れておきます。ここはスキップしてもらっても構いません。

ある列の単語(1単語または2単語の英単語が入っている)の文字数をカウントするということをやろうとしていました。ピリオドが含まれていたり(e.g., “dogs.”),2語の場合は間に空白もあるので(e.g., “beautiful lake”,それらを除去して文字数を数える必要があります。そのためには,str_extract,str_replace, str_lengthなどの文字列処理関数を使う必要があります。しかし,これらの関数はベクトルを受け取って処理をするので,データフレームを渡してもエラーが出てしまうという問題に直面しました。

select関数の挙動

データフレームからある特定の列を引っ張ってくるというとき,もちろん$を使って,dat$wordのようにするのが一番簡単なのでそれでもいいのですけども,dplyr使いの方はselect関数を使っている方も多いのではと思います。ただし,select関数はデータフレームの中から特定の列を引っ張ってくると,それがたとえ1列であってもdata.frame型になります。

よって,処理に使う関数がベクトル型を要求するものだとエラーが発生することになるわけです。しかもやっかいなのは,「じゃあas.vector()関数」を噛ませればいいやんとやってみてもそれでは解決しないからです。理由はよくわかりません。

  dat %>% 
  select(word) %>% #wordという列に文字数カウントしたい文字列があるとする
  as.vector() %>%
  is.vector() #このコードではFALSEとなります

pull関数がすること

pull関数は,要するにdat$x1のように$を使って,またはdat[, x1]のように[,]を使ってデータフレームの中の特定の列を指定するのと同じ挙動をするということです(参考)。よって,pull関数の出力はベクトル型になります。

  dat %>% 
  pull(word) %>%
  is.vector() #このコードではTRUEとなります

というわけで,1列だけ持ってくるときに関数を使う場合はpull()関数を使いましょうというのが結論です。私は結局こういう感じで文字数カウントをしました。

  dat %>% 
  pull(word) %>%
  str_extract(.,"[^\\.]+") %>% #ピリオドを除去
  str_replace(.,pattern = "\\s",replacement = "") %>% #半角スペースを除去
  str_length()->rt_dat$length #文字数をカウント

$を使うと次のようになります。

  str_extract(dat$word,"[^\\.]+") %>% #ピリオドを除去
  str_replace(.,pattern = "\\s",replacement = "") %>% #半角スペースを除去
  str_length()-> dat$length #文字数をカウントしてlengthという列に入れる

$を使ったほうが行数が少なくなるので,そっちのほうがいいような気もしますが,工程の見やすさでいうとpull関数を使うほうが上かなという感じがします。

おわりに

もともと文字数はカウントしてあったのですが,ちょっと査読者の指摘でフィラー項目も入れて分析をやり直さないといけなくなってこういった処理が必要になりました。データ型って基本といえば基本なのですが,以外に気づかずにエラーで困ることもあるので,select関数の挙動について勉強になるいい機会でした。

ということで,pull関数とselect関数,場合によって使い分けましょう。

なにをゆう たむらゆう。

おしまい。

[R] Collaborative Writing準備時短テク

はじめに

以前,下記のようなブログ記事を書きました。

一言で言えば,教師側で作ったテンプレファイルをフォルダごと学生と共有し,学生は自分の名前のついているWordファイル上で執筆活動を行い,教師側はリアルタイムでその進捗をモニタしつつフィードバックを出していくというようなライティング授業実践です。

今年度からは3年次のライティング授業も持っていて,その授業ではペアでのcollaborative writingも取り入れています。最初はペアはこちらで作ってファイルは学生に作らせてリンクを教師と共有という形でやっていましたが,それだとやっぱり使い勝手が悪い(教師側が自分のローカルからファイル閲覧できないとか他にも色々問題ががが)というのがあって,やっぱり教師が学生のファイルを作るほうがいいだろうという結論に至りました。

超えるべきハードル

1. 学生のペアリング

これは昔知り合いの川口先生がブログ記事に書いていたような気がするなと調べたらすぐ見つかったので,そこの記事で紹介されているものをそのまま使いました。

2. ペアリングした文字列をファイル名に転用できるようにする

上記ブログ記事先のやり方でやると,リスト形式で学生のペアリングリストが手に入ります。ただし,それをファイル名に転用できるようにしようとするとひと手間工夫が必要です。リストのそれぞれの要素に入っているクォーテーションマークでくくられた名前を結合して1つにまとめる必要があるからです。

私がもともとやっていたのは,文字列ベクトルの1つ目から順番にとってきて,それをファイル名にするというものでした。今回はペアですので2人(もし奇数なら3人組もできる)の名前を1つのファイル名にしようということになります。

リスト内の要素を結合するには次のようにします。

sapply(pairing,paste,collapse="&")->pairing2

pairingがリスト形式のグループ分けです。最終的にpairing2という変数には

"TAMURA Yu&KAWAGUCHI Yusaku" "TERAI Masato&FUKUTA Junya"

といったように名前が&でつながれた文字列のベクトルが入っています。あとはテンプレファイル複製のやり方と同じです。

setwd(here("Week9&10"));getwd() #Create a folder before runnning this code
dirnow <-getwd()
list1<-list.files()
print(list1)
original<-file.path(dirnow,list1) #Use the original file name
filename1<-paste(pairing2,list1,sep="_")
print(filename1) #Check all the file names
for (i in 1:length(filename1)){
file.copy(from=original,to=paste(dirnow,filename1[i],sep="/"))
}
list.files()

私は”rename”というフォルダ内にその週の課題ファイルを入れるフォルダを作っています。そのrenameという場所にRStudioがあるので,そこがワーキングディレクトリとなっています。それをその1つ下の階層に移してあげるのが1行目です。”Week9&10″というのがフォルダ名ということですね。そこに, “2022_Spring_AW_Week9&10.docx”という名前のテンプレファイルが1つはいっています。

3,4行目はそのコピー元ファイルがちゃんとあることの確認ですね。6行目でペアリングされた学生の名前が&で結ばれたものと,テンプレファイル名をアンダーバーでくっつけています。こうすることで,filename1という変数内には,

"TAMURA Yu&KAWAGUCHI Yusaku_2022_Spring_AW_Week9&10.docx" "TERAI Masato&FUKUTA Junya_2022_Spring_AW_Week9&10.docx"

のような最終的に変換されるファイル名が入ります。あとはfor関数の中でfile.copy関数を使ってファイルを複製し,そのときのファイル名をさきほど作ったfilename1の1番から最後までにしてあげるということになっています。

最後に元のテンプレファイルをフォルダから削除し,renameフォルダ内から”Week9&10″をひとつ上の階層(私の場合授業のフォルダ)にあげてからフォルダごと共有リンクをLMSに貼ればOKです。学生側はフォルダにアクセスし,自分の名前が入ったファイル上でペアと一緒にライティングをしていくことになります。

補足

もしも,ペアリングは自動ではなく手動でやりたいという場合は,エクセルなんかで2列になったものをコピーして,pairing変数にいれてあげればあとは同じようにできると思います。

おわりに

このRのルーティンを作るのに調べ物とかも含めて1時間くらいかかりました。そこで気づいたのですが,自分の担当しているのクラスは12人という少クラスで6ペアしかできないので,こんなことしなくても手作業複製とファイル名変更したほうが作業効率がよかったのではないか…という。

もっと大人数のクラスでcollaborative writingをやろうと思っていて,でもファイル管理がめんどくさい…という方の助けになれば。

なにをゆう たむらゆう。

おしまい。

WebClassのtips

自分の所属先のFDで,3月10日にWebClassというLMSのtips紹介みたいなことをやりました。他の大学でもWebClassを使っているところがあれば参考になるかもしれないなと思い,当日使ったファイルの共有リンクを貼っておきます。

https://www.dropbox.com/s/khjzajqeys3qbs8/2022MarchFD_Tamura.html?dl=0

HTMLファイルになっていて,Dropbox上でのプレビューが見れないと思いますので,ダウンロードしてご自身のデバイスで御覧ください。

大学でどういった運用をしているかや設定等によって使えない機能があったり見た目が違うということもあるかと思いますのであくまで参考としてください。細かいことについては私は開発者や導入者ではないのでわかりかねます。その点ご了承ください。

なにをゆう たむらゆう。

おしまい。

[R] mutateとacrossでデータの下処理を少しだけエレガントに

まえおき

私はdplyrは5年前くらいから使っていて,自分が扱うようなデータについて自分がやりたいことを(その表現方法のエレガントさは別として)表現することはできていました。ただ,近年dplyrはアップデートを重ねていました。昔覚えたやり方でやろうとしても,その関数は使えませんとか,その表記方法は違いますとか言われることが増えました。分析の下処理でやりたいことは基本的に研究が変わらないので同じです。よって,過去に自分が書いたスクリプトのコピペをすることが多いわけです。それができなくなっていたと。

特に,最近の更新でacross()という関数が導入されたことが変更として大きいなと思います。まだまだこのacross()に関する記事も少なかったので,自分が使うにあたって覚えたことをメモ代わりに書いておきます。ここでは,mutate関数と一緒に使うケースです。つまり,ある特定の列について,ある処理を施して,その処理を施した列をデータフレームに追加するという作業です。単純に列に対して処理を施すだけというのは結構記事があったんですが,列を追加することについては全部列挙するみたいな方法しか見つかりませんでした。そこでacross関数の出番というわけですね。

やりたいこと

例えば,今やってる研究のデータでは,データフレームの中に頻度のデータが入っています。これをログ変換したいとします。すると,これまでは以下のように書いていました。

log(dat$ColFreq)->dat$ColFreq_log #コロケーション頻度
log(dat$AdjFreq)->dat$AdjFreq_log #コロケーション内の形容詞の頻度
log(dat$NounFreq)->dat$NounFreq_log #コロケーション内の名詞の頻度
log(dat$MIScore)->dat$MIScore_log #Mutual Information Score

別にコピペ&書き換えみたいなことをしながらやればいいし,これでだめだってことはないんですけど,複数の列について

  1. 同じ関数を適用
  2. 列を追加する

という同じ動作をしているわけなので,これは一気にできたほうが応用可能性があがります。私は手作業でやるの無理みたいな列数のデータを扱うことはないんですが,もし仮にそういうデータを扱う場合には何十行も使うのは好ましくないし無駄な作業だといえます。そこで列に対して処理を施して追加するという機能があるmutate関数と,それを複数列に適用する際に便利なacross関数を組み合わせます。

やりかた

ちなみに,なんだかんだでdplyrのパッケージのPDFが一番わかりやすかったです(pp. 3-6のacross関数のセクションとpp. 43-46のmutate関数のセクション)。across関数の引数は,列(.cols),関数(.fns),追加する列の名前(.names)という3つの引数があります。よって,今回のケースで言えば列のところで頻度情報が入ってる列を選択し,関数はlogを選べばOKです。ただ,.namesがないと情報を上書きしてしまいます。.namesのところは手書きで全部列名指定してやらなかんのかと思いましたが,そんなことはありません。”{.col}”を使えば,もとの列名を使えます。これにあとは自分で好きなタグのようなものをつけてあげればいいですね。”{.fn}”というのも使えて,これは使った関数名が入ります。

ということで,以下のようにすれば頻度情報にログ変換して列追加という作業ができます。

dat%>%
  mutate(across(c(ColFreq, AdjFreq, NounFreq, MIScore),log,.names = "{.col}_log"))->dat

.namesの部分は”{.col}_log”としていますが,”{.col}_{.fn}”でも同じです。dat$ColFreq_log, dat$AdjFreq_log,dat$NounFreq_log,dat$MIScore_logという4つの列が追加されます。ちなみに,列指定の部分は列の数値(e.g., 1, 2)でも可能です。頻度の情報が5~8列目にあるなら,次のように書くこともできます。ある特定の文字列が含まれる列を選ぶcontains()関数starts_with()関数とかも使えるはずです(こういうのは調べれば結構例があります)。

dat%>%
  mutate(across(5:8,log,.names = "{.col}_log"))->dat

ちょっと応用

さて,mutate関数とacross関数でたいぶすっきりしたコードを書くことができました。そこでふと,私がもう一ついつも下処理で複数列に適用する作業を思い出しました。それは,変数の標準化です。いつもなら次のようにしてました。

dat$z.oqpt <-scale(dat$oqpt)[,1] #Oxford Placement Testの点数の中心化
dat$z.rating <-scale(dat$rating)[,1] #評定値の中心化

これも別に2行だけなので大したことないんですが,やってることは先ほどのログ変換と同じですので,これもmutate関数を使って書き直してみましょう。次のようになります。

dat%>%
  mutate(across(c(oqpt,rating),scale,.names = "z.{.col}"))->dat

これでうまくいっているようにも見えますが,実はscale関数って出力された結果がベクトルではありません(データ型を調べるとmatrix型なのがわかります)。よって,大抵の場合は分析に問題はありませんが,あとで(私の場合だと分析結果の図示とか)ベクトル形式が求められる関数に渡した際に問題が発生することがよくあります。データフレームをただ眺めるだけではそのことはわからないので,次のように工夫してあげる必要があります。

dat%>%
  mutate(across(c(oqpt,rating),~scale(.x)[,1],.names = "z.{.col}"))->dat

さきほどと関数部分の書き方が変わっているのがわかると思います。このように”~”をつける書記法はpurrr-styleと呼ばれるそうですが,これは一般的には関数内の引数を指定する場合によく用いられます。例えば,~mean(.x, na.rm=T) のように使います。”na.rm=T”は欠損値は外して関数を適用するという設定のようなものです。今回は引数の設定ではなく,~scale(.x)[,1]としています。”[,1]”とすることで,行列の1つ目の要素(つまりこれは標準化された数値のベクトル)だけを出力してくれます。ちなみに,この方法で.namesに{.fn}をつかって次のようにすると,出力される列名はoqpt_1, rating_1のようになりました(理由は不明)。

dat%>%
  mutate(across(c(oqpt,rating),~scale(.x)[,1],.names = "{.col}_{.fn}"))->dat

おわりに

というわけで,改良されているんだろうけれども前のやり方に慣れてるこっちからしたらアップデートたびにコードを書き換えるのまじで面倒…って思っていたのですが,調べてみるとやっぱり便利でしたというお話でした。

またこういう系のことで新しく覚えたことがあれば記事に書こうと思います。

なにをゆう たむらゆう。

おしまい。

学会のSNS禁止もなんかわかる気がしてきた

はじめに

Photo by Brett Jordan on Pexels.com

今はコロナの影響でどこも学会がオンラインになってるわけですが,そうなるもっと前から,つまり対面で学会をやっていたときから,学会の発表に関してSNSに投稿することを禁止するルールを設ける学会があったりします。昔は,そんなことを禁止する必要ある?みたいなことを思っていました。しかしながら,最近考え方も変わって,まあそういうことをしたくなる気持ちも理解できるなとなったという話です。

Twitterの使い方も変わった

anf先生とのポッドキャストでも話したことですが,昔と今ではTwitterの使い方(雰囲気)も変わったよねみたいなところがあります。その時はノスタルジックな感じで喋りましたし,昔はよかったなみたいなのもある面ではそう思うところがあります。

ただ,アカデミアの人がTwitterで炎上するみたいなのを最近見ていると,本来オープンな場所であるべきSNSでクローズドな場所でやるべきやりとりをしていることが原因の少なくない部分を占めているんじゃないかなと思うところがあります。そして,それってまさに自分が楽しいなと昔思っていたような部分でもあるんですよね。まさにオープンな場所で,いろんな先生と個人的なやりとりができる,そのことが特にアメリカにいた自分にはすごく刺激的でした。当時はオンライン学会なんて発想もおそらくなかったような時代だと思いますし,学会の様子をツイートしてくれる人たちの書き込みを見ながら様子を想像したりするのも好きでした。

その証拠に,togetterで学会に関するツイートのまとめを参加してもいない(というか日本にすらいなかった)自分がやっているということもありました(メニューのTogetterまとめにリンクあります)。そこから数年経って,学会での発表についてSNSに投稿することを禁止するみたいなルールを設ける学会の存在を知りました。当時はそれに反対する気持ちもありましたが,今はまあそういうこともしたくなるわなぁと思ったりもします。

学会員(参加者,もっといえば発表者に)有益であるべき

発表に対するなにかしらの発言て,本来は準備をして発表した発表者に直接届けられるべきだなというのがいまの気持ちです。特に,研究の問題点を指摘する場合にはよりそう思います。なぜなら,その発言が発表者に伝わらないと何も生まれないからです。発表者に届けば,それを聞いた発表者の研究が将来的に改善して,そのことが学会(学界)にポジティブな貢献をする可能性があります。一方で,ツイッターに書いて身内で「あれはないよなー。」みたいなやりとりしたところで,結局それは身内でやってるだけで学会(学界)への貢献はゼロに等しいです。研究は研究分野を発展させるという目的でやってるし学会もそういう意図がある組織なわけです。そこに貢献するにはどうすればよいかという視点で昔は考えられていかなった,つまり自分自身の視点でしか研究を見てなかったんだなというのが反省です。

私はどちらかというと昔から手を上げて質問はしないけどツイッターには書くみたいなのをやっていたほうで,それやるなら質問しなさいということを目上の先生に言われた記憶もあります。よって,昔の自分を棚に上げてえらそうなことを言っているというように思われるかもしれません。ただ,私はそれからはあまり学会参加中に発表内容について書くことはしなくなりました。

アウトリーチ的な意味合いはあるにせよ

学会のことをつぶやくというのは,アウトリーチ的な部分でポジティブに作用する可能性はあると思います。学会でどんなことが起こっているのかをツイートすることで,学会員ではない人や学会には入っていない関係者,そしてさらにそれよりも外側の一般の人達にまで学会で行われていることを届けることができる可能性があります。ツイートを見て,面白そうだなと思ってその学会に入ろうとか,その学会の次のイベントに参加しようとか,そういうこともあるでしょう。まさに私が日本の学会に参加している人たちのツイートを見て,学会楽しそう!と思ったのと同じように。

「メモ代わり」ならメモ帳に書けば良し

もしかすると,ツイッターは自分のメモ代わりに使っているから,そういう目的でつぶやいているのであって,それを誰かに禁止される筋合いはないという意見を持つ人もいるかもしれません。もしそうだとしたら,メモこそオープンなところに書く必要がないからメモ帳に書けばいいということになります。もちろん,そういったメモ的な書き込みに対して誰かが反応して,そこから有意義な議論に発展することもあると思います。そうなれば,その議論に参加している人も,そしてその議論を見ている人にとっても有益です。そういうのも私が昔ツイッターが面白いと思っていた理由でもありますから。しかしながら,その有益性は残念ながら発表者には一ミリも還元されないという点で,やはり良くないと思っています。発表者の人が発表にかけた準備の労力だったり,実際に発表することにかけた労力,そういうものにある意味では「タダ乗り」して自分だけ有益な議論をしているわけですから。

本来は,質疑応答の時間をそういった有益な議論の時間にすることに全員がコミットするべきだと思います。特に今はオンライン学会なわけで,ツイッターに書くならZoomのチャット欄に書いたって同じじゃんと思うこともしばしばあります。もちろん,文字で伝える場合は口頭でやり取りするのと違って誤解(誤読)の可能性がないように,なおかつ自分の質問を明確に,伝えないといけません。よって,そうやって質問しようとしたら非常に長い文章を書かなけれればいけなかった,というように,チャットでの質問のほうが逆に難しいということもあるかもしれませんが(私は参加してませんでしたが,先日寺沢さんがそういうことをツイートしていたような)。

ただし投稿がすべて害悪とは言い切れないので難しい

ただし,ツイッターならではというか発表者にも参加者にとっても有益なツイートというのも十分にありえます。例えば,発表者が引用している文献情報(本や論文のリンク)をツイートするということがあります。今では論文であれば出版社のウェブサイト,本であればアマゾンのリンクが検索すればすぐに見つかります。これをツイートしている人がいれば,同じ発表を聞いている人にとっては自分が探す手間が減りますから助かります。こういうのであれば,自分のメモ代わりであってもそれが他者にとっても有益になりますし,なおかつ発表者にとっても自分が引用している文献を他の人がアクセスしやすくなることはメリットがあるでしょう。

また,発表者が取り組んでいる研究プロジェクトのウェブサイトだったり,あるいはその発表者自身のウェブサイトなどがツイートされれば,これは発表者(の研究)の宣伝になるわけですから,発表者にとっても大きなメリットです。そして,参加者にとっても(参加せずにツイッターだけ見ている人にとっても)その発表者の取り組んでいる他の研究へのアクセスもしやすくなって,参加者にとってもメリットになります。

おわりに

おそらく,本来のテキスト中継( tsudaる)みたいなツイートであれば,それは参加していない人にも発表の内容が届けられるので発表者にとっても(発表を聞いてもらえる人が増えるという意味で)メリットがあります。おそらく問題になってくるのは,本来質疑応答で発表者に対して向けられるべきであろう内容がツイートされる時なのかなと思います。SNS禁止という発想はわからないでもないが,かといって発表者に還元されないような,酷いケースだと発表者が損だと感じてしまうようなツイートを放置しておくのも好ましくない,とはいってもそういうのを規制するルール作りも難しい,というのが現状なのかなと。ルールを作るとそれを監視する必要がありますから。

私個人としては,自分ができるだけ発表者に,そしてそこに参加している人たちにとって有益かどうかという観点でその場での質問と,ツイッターに投稿することというのを分けていこうかなと思っています。

なにをゆう たむらゆう。

おしまい。

[R] [Excel] 多肢選択の正答をランダムにする

はじめに

いままであまり深く考えたことなかったんですけど,多肢選択式のテストを作るとき,正答をどれに指定するかって規則性がないように,同じものが連続にならないように,とかを「なんとなく」,「雰囲気で」やってきたところがあります。それを,ちゃんとランダムにできないかな,というお話。

R編

なにはともあれ,Rを使います。エクセルでもできるのにRです。Rなら一瞬です。

sample関数とLETTERS関数の組み合わせ

要するに,例えば4択問題であればABCDの4つの中からランダムに1つ選ぶのを問題数分だけ繰り返すってことになりますよね。それを表現してあげれば良いだけです。めっちゃ簡単。

例として,ABCDの4択問題を20問作ることにしましょう。

sample関数を使います。sample関数は次のような引数を取ります。

sample (x, size, replace = FALSE, prob = NULL)
  • x: もとデータのベクトル(今回はこれをABCDにしたい)
  • size: サンプリング回数(20問なのでここに20をいれる)
  • replace: 繰り返しありかどうか(デフォルトだとFALSEで同じものが繰り返し出てこないようになってますが,今回はむしろ繰り返し出てきてOKなのでTRUEにしないとだめ)
  • prob: サンプリングの重み付け確率(どれが何%の割合でてくるようにするか決められます。後述します)

さて,次に問題になるのは,ABCDをベクトルにすることですね。もちろん,

> d <- c("A", "B", "C", "D")

で簡単にできます。よって,

> d <- c("A", "B", "C", "D")
> sample (d, 20, replace = TRUE)

これでOKです。ただ,ほんのちょっとだけ便利なやり方は,LETTERSを使うことです。Rはデフォルトで,LETTERSの中に,A~Zまでのアルファベットが入っています(小文字のa~zはlettersです。

> LETTERS
 [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"

今回は,A~Dの4つだけでいいので,1番目から4番目までをつかいます。sample関数と組み合わせて…

> sample(LETTERS[1:4],20,replace = TRUE)
 [1] "B" "D" "C" "A" "D" "D" "C" "A" "A" "C" "B" "A" "D" "A" "B" "C" "C" "C" "A" "C"

これでばっちりですね。もしも,「えーなんかこれC多くない?」みたいなことが気になる方はこのコード何回か走らせていい感じの組み合わせが出たらそれを使えばいいんじゃないかと思いますが,probでABCDがでる確率の重み付けをつけてあげることもできます。

> sample(LETTERS[1:4],20,replace = TRUE, prob=c(0.25,0.25,0.25,0.25))
 [1] "D" "B" "A" "C" "C" "A" "C" "D" "C" "A" "A" "C" "B" "B" "B" "D" "B" "D" "B" "D"

絶対にいつでも等確率で現れるわけではないみたいで,4つだったり6つだったりするものもありますが,完全なランダムよりは出現確率が揃ってるんじゃないかなと。もしもこれをエクセルにはりつけたければ,出力されたものをそのままコピペして,Text Import Wizardでスペース区切りにしてあげればOKです。縦にしたい場合は転置してください。

Excel編

Excelでもそこまで難しくないです。INDEX関数とRANDBETWEEN関数を組み合わせます。下の画像のようにすればOKです。

B3からB21までは,B2を下にコピーしたものが入ってます。INDEX関数の第一引数で参照元の範囲をしています。これがつまりABCDってことですね。そして,次の引数が縦位置の指定です。本当はこの後ろの第三引数で横位置指定もできますが,今回は1列だけなのでこれでOKです。この位置指定が1のときはA,2のときはB,3のときはC,4のときはDってな感じになるというわけです。そして,RANDBETWEEN関数をここに使うことで,1から4がランダムに出てくれる=ABCDがランダムに出てくれる,ということになります。ちなみに,RANDBETEEN関数は,始点と終点の数値を入れればその間の整数をランダムに返す関数です。

ちなみに,横位置指定を使おうと思えば,ABCDを1列ではなく2列に分割することになります。こちらのほうが数式が長くなるのでおすすめしないですが,INDEX関数の挙動のイメージを理解するために見てみます。

こっちだと範囲が2*2のマトリックスになるわけですね。そして,第二引数(縦位置指定)で1か2のどちらかの数字,第三引数(横位置指定)で1か2のどちらかの数字をランダムに返すようになっています。つまり,(1, 1), (1, 2), (2, 1), (2, 2)の4つのパターンがランダムにできて,それに対応するABCDが返ってきます。(1, 1)ならAというような感じ。もっと大きなデータを扱う場合には縦横指定が必要になるでしょうが,今回の用途には不要なので,ABCDを一列にするほうがいいと思います。

おわりに

別に適当に正答指定して何も悪いことはないのですが,ランダムにするのってできるかな?という頭の体操でした。

なにをゆう たむらゆう。

おしまい。

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

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

なにをゆう たむらゆう。

おしまい。