コンテンツへスキップ

定性コーディングのための分析メモ

Potato のメモは、アイテム、テキストの一節、描かれた図形に付けられ、返信を受け付けます。課題として提起されたメモは、誰かが課題を解決するまで未解決のままです。

Potato のメモは、アイテム、アイテム内のテキスト選択、または画像上に描かれた図形に付けられる、自由記述のノートです。メモを読めるユーザーは誰でもそのメモに返信でき、課題として提起されたメモは、作成者、担当者、または裁定者が課題を解決するまで未解決のままです。メモは、QDA モードの有無にかかわらず、どの Potato プロジェクトでも動作し、Potato はメモを、アノテーションファイルではなくプロジェクトのデータベースに保持します。メモは Potato 2.6.0 で登場し、返信と課題は 2.12.0 で登場しました。

分析メモは、研究者がコーディング中に、データとコードについて書くノートです。たとえば、あるコードがなぜ一節に当てはまるのか、またコードブックのどこに新しいルールが必要かを書きます。メモの記述は、グラウンデッド・セオリーの一部として最もよく説明され、Birks、Chapman、Francis(2008)は、質的研究の諸手法にわたってメモの記述を推奨しています。著者らの説明では、メモは、アナリストが生のデータから、データを説明する抽象概念へ移るのを助けます。コーディングチームでは、メモはコードの背後にある判断も記録し、下のエクスポートは、そうしたノートを監査証跡に変えます。

各メモは、次のことを記録します。

  • アンカー。 メモは、アイテム全体、アイテムのテキストの文字範囲(quote バッジで表示)、または描かれた一つの図形(図形のラベルとタイプ、たとえば car box で表示)に付きます。
  • 公開範囲。 メモは private(デフォルト)または shared です。
  • スレッド。 返信は最初のノートの下に付き、最初のノートの公開範囲を引き継ぎます。
  • 課題のステータス。 課題は open または resolved で、担当者を一人置くことができ、誰がいつ課題を解決したかが記録されます。
  • 保存。 メモは、Add note をクリックした時点で、<task_dir>/project.sqlite の memos と memo_threads のテーブルに保存されます。

メモをオンにする

メモは、標準のプロジェクトではオフで、QDA モードとソロモードの下ではデフォルトでオンです。プロジェクトは、annotation_ui ブロックでメモをオンにします。以下の設定は、span スキームと非公開のメモを使って、インタビューの抜粋をコーディングするチームを設定します。adjudication ブロックはリードアナリストを指名し、裁定者はプロジェクト内のすべてのメモを読めます。

yaml
annotation_task_name: Clinic access interviews
task_dir: .
output_annotation_dir: annotation_output/
data_files:
- data/excerpts.json
item_properties:
  id_key: id
  text_key: text
 
annotation_ui:
  memos: true
  visibility: private
 
adjudication:
  enabled: true
  adjudicator_users: [lead_analyst]
 
annotation_schemes:
- annotation_type: span
  name: codes
  description: Highlight a passage and apply a code
  labels: [transport barriers, cost concerns, provider trust]

引用レポートには span スキームが必要なため、span スキームはエクスポートにとって重要です(メモのエクスポートを参照)。四つのキーがメモを制御します。

オプションデフォルト説明
annotation_ui.memosオフ。qda_mode.enabled または solo_mode.enabled が true の場合はオンNotes パネルを表示し、/api/memos のエンドポイントをオンにします。明示的な true または false は、QDA モードとソロモードを上書きします。
annotation_ui.visibilityprivatevisibility フィールドなしで API を通じて作成されたメモの公開範囲。private と shared 以外の値は、private にフォールバックします。
qda_mode.memos.show_sidebar_by_defaulttrueQDA モードの下で、アノテーターが閉じるまで、各アイテムで Notes パネルを開きます。
qda_mode.memos.enabledtrueQDA モードの下で、false にすると、Notes パネルは閉じた状態で始まります。メモは引き続き使え、メモをオフにするキーは annotation_ui.memos: false です。

QDA モード以外では、Notes パネルは閉じた状態で始まり、アノテーターはページの右端の Notes ボタンでパネルを開きます。パネルを閉じると、ブラウザータブのセッションの残りの間、以降のアイテムでもパネルは閉じたままです。メモがオフの場合、Potato は Notes ボタンを表示せず、/api/memos のエンドポイントは 503 を返します。コンポーザーの公開範囲メニューは、すべてのプロジェクトで Private から始まり、annotation_ui.visibility はメニューを変えません。共有のメモを望むチームは、コーダーに、新しいメモごとに Shared を選ぶよう求めます。

Potato は、各メモをプロジェクトの annotation_task_name の下に分類します。設定でタスクの名前を変更すると、古い名前で書かれたメモは見えなくなります。行は project.sqlite に残り、古い名前に戻せばメモが戻ります。

Notes パネルでのメモの記述

Notes パネルは、現在のアイテムのメモを古い順に一覧し、各スレッドの返信は最初のノートの下に表示されます。メモを追加するには、次のようにします。

  1. アノテーションページの右端にある Notes をクリックします。
  2. メモを一節にアンカーするには、先にアイテム内のテキストを選択し、Attach to selected text にチェックを入れます。メモを描かれた図形にアンカーするには、画像のキャンバスで図形を選択し、Attach to the selected shape にチェックを入れます。
  3. コンポーザーにノートを入力します。
  4. ノートを課題として提起するには、Raise as an issue to resolve にチェックを入れます。任意で、課題を解決すべき人のユーザー名を Assign to に入力します。
  5. Visibility で Private または Shared を選び、Add note をクリックします。

各メモには、現在のユーザーが使えるボタンが表示されます。Reply はすべてのスレッドに表示され、Resolve または Reopen と Assign は、ユーザーが変更できる課題に表示され、Edit と Delete はユーザー自身のメモに表示されます。裁定者には、他のユーザーのメモにも Delete が表示されます。最初のノートを編集すると、テキストだけでなく、ノートの公開範囲も変えられます。

テキストのアンカーは、アイテムの表示されたテキスト内での、選択範囲の開始と終了の文字オフセットを記録し、終了オフセットは含まれません。選択がカウントされるのは、アイテムの主要なテキスト表示の内側のみです。図形のアンカーは、描かれた図形に保存された ID がないため、図形のスキーム、タイプ、ラベル、正規化された座標を記録します。メモの図形バッジをクリックすると、保存された座標を照合して、その図形をもう一度選択します。その図形がその後移動または削除されていた場合、パネルは、図形が描かれたとおりには画像上にないことを報告します。

誰がメモを読めるか

非公開のメモを読めるのは、作成者と裁定者です。共有のメモは、プロジェクトのすべてのユーザーが読めます。課題の担当者は、課題が非公開であっても、その課題のスレッドを読み、返信できます。メモに関するその他のルールは次のとおりです。

  • メモのテキストまたは公開範囲を編集できるのは、作成者のみです。
  • メモを削除できるのは、作成者または裁定者です。スレッドの最初のノートを削除すると、返信も削除されます。
  • スレッドを読める人は誰でも返信できます。返信は最初のノートの公開範囲に従い、最初のノートの公開範囲を後から変更すると、返信にも適用されます。
  • ユーザーが読めないメモに対しては、すべての操作が 404 を返します。Potato は、存在しないメモに対しても同じ応答を返します。

メモにとって、裁定者とは、adjudication.enabled が true の間に adjudication.adjudicator_users に列挙されたユーザー名です。Potato がメモについて確認するのは、そのリストだけです。RBAC の admin ロールを持っていても、リストにないユーザーは、一般のアノテーターと同じメモを読みます。

非公開のメモが非公開なのは、アノテーションのインターフェース内に限られます。引用レポートのエクスポートを実行する人や project.sqlite を開く人は、非公開のメモを含め、すべてのメモを読みます。コーディングを始める前に、エクスポートについてコーダーに伝えてください。

共有のメモがあると、コーダーはコーディング中に互いの推論を読めます。二人のコーダーが、コーダー間信頼性のチェックのために同じ抜粋を独立してコーディングするとき、共有のメモは二人目のコーダーの判断を固定し、コードブックとは無関係な理由で一致度を高めることがあります。信頼性のラウンドの間は、メモを非公開に保ってください。ラウンドの後で、コーダーは各非公開のメモを Edit で開き、調整の会議のために Shared に切り替えられます。

返信と課題

すべてのメモがスレッドを開始します。返信には、最初のノートとは別の公開範囲もステータスもありません。Raise as an issue to resolve にチェックを入れると、最初のノートにステータス open が付きます。課題は、コーディングが先に進む前に答えが必要な質問、たとえばコードブックが決めていないコードの境界などに向いています。課題の権限は次のとおりです。

操作その操作ができる人
返信スレッドを読める人なら誰でも
課題の解決または再開課題の作成者、担当者、または裁定者
課題の割り当てまたは担当者のクリア課題の作成者または裁定者

課題を解決すると、誰がいつ解決したかが記録され、課題を再開すると、その両方のフィールドがクリアされます。割り当てをクリアすると、担当者は非公開の課題へのアクセスを失います。未解決の課題がアノテーターに割り当てられている場合、Notes ボタンには Notes · 2 assigned to you のように件数が表示され、パネルは上部に課題を一覧します。アノテーター自身のキューにあるアイテムの課題には Go to item ボタンが付き、キューの外にあるアイテムの課題には、キューにないことを示すラベルが付きます。jumping_to_id_disabled: true を設定すると、Go to item ボタンが取り除かれます。

割り当てをチャットのチャンネルやトラッカーに送るには、ウェブフックを memo.issue_assigned イベントに登録します。このイベントは、課題に新しい担当者が付くたびに発火し、メモの ID、アイテムの ID、担当者、課題を割り当てたユーザー、ステータスを送ります。課題が非公開の場合があるため、ペイロードにはメモのテキストは含まれません。

管理ダッシュボードの課題

メモがオンのとき、管理ダッシュボードの Overview タブには、未解決の課題の数と解決済みの数を示す Open issues タイルが表示されます。管理 API は、非公開のものを含め、課題そのものを一覧します。

bash
curl -H "X-API-Key: $POTATO_ADMIN_KEY" \
  "http://localhost:8000/admin/api/memo_issues?status=open"

レスポンスには、課題ごとに一つの項目があり、新しい順で、メモのテキスト、作成者、アイテムの ID、アンカー、担当者、ステータス、解決者が含まれます。解決済みの課題には ?status=resolved を使い、両方を取得するにはパラメータを省略します。このエンドポイントは課題のみを一覧します。通常のメモは、エクスポートまたは裁定者のアカウントを通じて、プロジェクトリードに届きます。

メモのエクスポート

quotation_report エクスポーターは、コーディングされたスパンごとに一行の CSV を書き出します。include_memos=true を指定すると、エクスポーターはメモと返信ごとに一行を追加します。

bash
python -m potato.export -c config.yaml -f quotation_report \
  --option include_memos=true -o ./export/

このコマンドは ./export/quotations.csv を書き出します。メモの行は、スパンの行と同じ九つの列を使います。

列メモの行での値
schema(memo)、(memo reply)、(issue: open)、または (issue: resolved)
codeスレッドの公開範囲、private または shared
textメモのテキスト
start, endテキストのアンカーの文字オフセット。それ以外は空
fieldテキストのアンカーでは text。それ以外は空
instance_idメモが付いているアイテム
source_docアイテムのテキストの最初の 200 文字
coderメモの作成者

エクスポーターが動作するのは、設定に span スキームが少なくとも一つある場合のみです。radio や multiselect の質問だけでコーディングされた調査では、No span annotation schema found in config というエラーになります。メモの行にはタイムスタンプも担当者もなく、図形にアンカーされたメモは、空のオフセットでエクスポートされます。

日付付きの監査証跡が必要な場合は、二つのメモのテーブルに直接クエリを実行します。以下の sqlite3 コマンドは、プロジェクト内のすべてのメモを、UTC での作成時刻、スレッドのステータス、担当者、解決者とともに一覧します。

bash
sqlite3 -header -csv project.sqlite "
  SELECT m.instance_id, m.created_by, datetime(m.created_at, 'unixepoch') AS created,
         m.visibility, t.parent_id, t.status, t.assignee, t.resolved_by, m.body
  FROM memos m LEFT JOIN memo_threads t ON t.memo_id = m.id
  WHERE m.project = 'Clinic access interviews'
  ORDER BY m.created_at" > memos.csv

空でない parent_id は返信を示し、スレッドの最初のノートを指します。Potato は時刻を Unix 秒として保存し、resolved_at と updated_at は created_at と同じように変換されます。

メモは、REFI-QDA の .qdpx エクスポートには入りません。設定が annotation_ui.memos: true を設定している場合、.qdpx エクスポーターは、メモが除外されたことを警告します。そのキーなしで QDA モードまたはソロモードの下にある場合は、エクスポートは警告なしにメモを除外します。プロジェクトを別の QDA プログラムに移すときは、メモを引用レポートで別にエクスポートしてください。

potato snapshot create が構築するアーカイブは project.sqlite を含み、potato deploy pull のアーカイブもそのファイルを含みます。そのため、どちらのアーカイブも、非公開のものを含め、すべてのメモを保持します。スナップショットのコンテンツハッシュは、設定、調査のファイル、アノテーションをカバーします。ハッシュはデータベースを含まず、新しいメモはハッシュを変えません。プロジェクト・スナップショットを参照してください。

メモ API

Notes パネルは、アノテーターのログインセッションで認証される、/api/memos の下の REST API を使います。スクリプトも、同じエンドポイントを呼び出せます。

リクエスト目的
GET /api/memos?instance_id=<id>ユーザーが読める、一つのアイテム上のメモと返信。それぞれに can_edit、can_delete、can_resolve、can_assign が付く
POST /api/memosinstance_id、body、visibility、anchor からの新しいメモ。課題の場合は issue: true と任意の assignee を加える
POST /api/memos/<id>/replybody を持つ返信
PATCH /api/memos/<id>body、visibility、status(open または resolved)、assignee(クリアするには空)の変更
DELETE /api/memos/<id>メモの削除。メモが最初のノートの場合は返信も削除
GET /api/memos/issues?status=open&assignee=meユーザーが読める、プロジェクト全体の課題

テキストのアンカーは {"start": 48, "end": 98, "field": "text"} で、図形のアンカーは {"shape": {"schema": ..., "type": ..., "label": ..., "coordinates": ...}} です。プロジェクトにないアイテム ID に対する POST は、400 を返します。

例

Potato のリポジトリには、メモの例が含まれています。この例を、Potato のチェックアウトから実行します。

bash
python potato/flask_server.py start examples/advanced/memos-example/config.yaml -p 8000

この例は、一つの感情の質問を持つ四つの短い商品レビューに対して、非公開のメモをオンにします。この例には span スキームがなく、引用レポートはこの例のメモをエクスポートできません。QDA モードの例には、コードブックに基づく span スキームがあります。エクスポートを試すには、examples/advanced/qda-mode-example/config.yaml を実行してください。

関連資料

実装の詳細については、ソースドキュメントを参照してください。

参考文献

Birks, M., Chapman, Y., and Francis, K. (2008). Memoing in qualitative research: Probing data and processes. Journal of Research in Nursing, 13(1), 68–75. doi:10.1177/1744987107081254