二人のコーダーでインタビュー記録をコーディングし、アルファを報告する
二人のコーダーが Potato で一つのコードブックをインタビュー抜粋に適用し、コードごとの Krippendorff のアルファを報告し、不一致を調整して、QDPX プロジェクトをエクスポートします。
インタビューをチームでコーディングする質的研究者や混合研究法の研究者は、このチュートリアルに従って、Potato 2.13.1 で二人のコーダーに、オープンライセンスの六つのインタビュー記録をコーディングさせ、方法のセクションで Krippendorff のアルファを報告し、不一致を調整し、コーディング済みのプロジェクトを NVivo、ATLAS.ti、MAXQDA で作業する同僚に引き渡すことができます。このチュートリアルは、コードブックがすでにあることを前提としています。Potato の QDA モードは、一人のアナリストがインタビューを読んでコードブックを育てていく、より早い段階に向いており、QDA モードの記事がその段階を順に説明しています。質的データ分析ソフトウェアの比較は、各ツールの価格と機能を扱い、Potato での質的研究は、Potato の質的研究向けの機能を一か所にまとめています。
インタビュー
記録は、Mário Rosado de Souza、Robert Haines、Markel Vigo、Caroline Jay が Zenodo に登録した What makes research software sustainable? Anonymized interview transcripts(参考文献 2)のものです。この登録データには、研究ソフトウェアの開発者への 19 件のインタビューがインタビューごとに一つの PDF として含まれ、ライセンスは CC BY-SA 4.0 です。これらのインタビューの基になった研究は CHASE 2019 に掲載されました(参考文献 1)。記録から作成して共有するファイル(下の抜粋ファイルなど)には同じライセンスが適用され、四人の著者の表示が必要です。このチュートリアルでは、最初の六つのインタビューを使います。六つのすべてで、インタビュアーは、持続可能なソフトウェアとは何か、どの特徴がソフトウェアを持続可能にするのか、ソフトウェアが維持されないと何が起こるのかを尋ねています。Zenodo のレコードから Interview01.pdf から Interview06.pdf までをダウンロードしてください。
信頼性の評価には固定された単位が必要で、両方のコーダーが同じテキストの同じ部分について同じ問いに答えます。ここでの単位は、参加者の一つの回答です。下のスクリプトは、pdftotext(Poppler に含まれます)が各 PDF をテキストに変換した後の記録を読み込み、20 語以上の参加者の回答をすべて残し、各回答の隣にインタビュアーの直前の質問を記録します。
"""Split interview transcripts into one excerpt per participant answer.
Usage: python prepare_excerpts.py transcripts/*.txt > data/excerpts.jsonl
"""
import json
import re
import sys
from pathlib import Path
TURN = re.compile(r"^\s*(I\d*|P\d*)\s*[-:]\s*(.*)$", re.IGNORECASE)
MIN_WORDS = 20 # shorter answers ("Yeah", "Right") are not coded
for path in sys.argv[1:]:
interview = Path(path).stem.replace("Interview", "I").replace("interview", "I")
turns, speaker, words = [], None, []
for line in Path(path).read_text(encoding="utf-8").splitlines():
line = re.sub(r"!\s*$", "", line).strip() # the PDFs end some lines with "!"
match = TURN.match(line)
if match:
if speaker:
turns.append((speaker, " ".join(words)))
speaker, words = match.group(1).upper()[0], [match.group(2)]
elif line and speaker:
words.append(line)
if speaker:
turns.append((speaker, " ".join(words)))
question, n = "", 0
for speaker, text in turns:
text = re.sub(r"\s+", " ", text).strip()
if speaker == "I":
if "?" in text: # keep the last question, skipping "Mm" and "I see"
question = text
elif len(text.split()) >= MIN_WORDS:
n += 1
print(json.dumps({"id": f"{interview}-{n:02d}", "interview": interview,
"question": question, "text": text}, ensure_ascii=False))Potato をインストールし、六つの記録に対してスクリプトを実行します。
pip install potato-annotation==2.13.1
mkdir -p transcripts data
for f in Interview0[1-6].pdf; do pdftotext -layout "$f" "transcripts/${f%.pdf}.txt"; done
python prepare_excerpts.py transcripts/*.txt > data/excerpts.jsonl六つのインタビューから 52 件の抜粋が得られ、最も短いインタビューで 5 件、最も長いインタビューで 15 件です。data/excerpts.jsonl の各行は一つの抜粋で、ここでは回答を短くして示します。
{"id": "I01-07", "interview": "I01", "question": "Okay. Um, regarding the software you developed, was sustainability a consideration?", "text": "Sustainability most certainly was a consideration. ..."}記録では話者のラベルが I1: と I1 - の二つの形式で書かれており、スクリプトは両方を読み取ります。インタビュー 1 では、インタビュアーの最初の質問が参加者の発話としてラベル付けされており、このインタビューの最初の四つの抜粋には、回答の隣に質問がありません。コーディングを始める前に、各インタビューから数件の抜粋を PDF と照らし合わせて読んでください。
コードブック
コードブックには十個のコードがあり、六つのインタビューを読んだ後に書かれました。九つのコードは参加者が挙げるテーマを表し、十番目のコード「No code applies」は、すべての抜粋に回答を与えます。Potato の信頼性エクスポートは、コーダーが何も選ばなかった抜粋を除外します。十番目のコードがないと、一方のコーダーがテーマを見つけ、もう一方が見つけなかった抜粋は、不一致として数えられる代わりにアルファの計算から脱落します。各コードの定義はそのコードの tooltip であり、コーダーはコードにカーソルを合わせると定義を見られます。
一つの回答が二つのテーマに触れることはよくあるため、コードブックは multiselect 質問で記録します。Potato は、CSV ファイルからコードブックを hierarchical_multiselect 質問に読み込むこともでき(内容分析)、この質問タイプは百個のコードを持つ入れ子のコードブックに向いています。2.13.1 では、階層型の質問タイプには、このチュートリアルのワークフローにとって一つの欠落があります。裁定ページでは、裁定者が一方のコーダーの回答を採用できますが、二つを組み合わせることはできません。2.12.1 でも、codebook と qdpx のエクスポートは、その質問のコードを含めていませんでした。
設定
下の設定は完全なもので、2.12.1 と 2.13.1 の両方で python -m potato.validate_cli config.yaml --strict を通ります。
annotation_task_name: Research software sustainability interviews
task_dir: .
output_annotation_dir: annotation_output/
data_files:
- data/excerpts.jsonl
item_properties:
id_key: id
text_key: text
user_config:
allow_all_users: true
users: []
# Both coders code every excerpt independently
num_annotators_per_item: 2
instance_display:
fields:
- {key: question, type: text, label: Interviewer}
- {key: text, type: text, label: Participant, span_target: true}
annotation_schemes:
- annotation_type: multiselect
name: codes
description: Which codes apply to this answer? Hover over a code for its definition.
humanize_labels: false
labels:
- {name: Documentation, tooltip: "Manuals, API descriptions, examples, or software that explains itself"}
- {name: Testing, tooltip: "Automated tests, or the effort and limits of writing them"}
- {name: Code design, tooltip: "Modular, generic, narrowly scoped, or well-commented code"}
- {name: Reuse of libraries, tooltip: "Building on maintained libraries instead of bespoke code"}
- {name: Public source code, tooltip: "Version control, GitHub, or another place where anyone can find the code"}
- {name: User community, tooltip: "People or organizations who use the software, rely on it, or answer questions about it"}
- {name: More than one maintainer, tooltip: "Someone other than the original developer can build, maintain, or take over the software"}
- {name: Funding, tooltip: "Grants, budgets, or money to keep the software maintained, or the lack of them"}
- {name: Software decay, tooltip: "Software stops working as platforms, libraries, or servers change, or is abandoned"}
- {name: No code applies, tooltip: "The answer touches none of the codes above"}
- annotation_type: span
name: quotes
description: Highlight the words that show each code you ticked.
target_field: text
humanize_labels: false
labels: [Documentation, Testing, Code design, Reuse of libraries, Public source code, User community, More than one maintainer, Funding, Software decay]
adjudication:
enabled: true
adjudicator_users: [lead]
min_annotations: 2num_annotators_per_item: 2 はすべての抜粋を両方のコーダーに送り、Potato はどちらのコーダーにも相手のコードを見せません。instance_display はインタビュアーの質問を回答の上に置き、span_target: true は、コーダーが回答の中だけでハイライトできるようにします。quotes 質問は、各コードの根拠となる語句を、執筆のために収集します。Potato は、チェックされたコードから信頼性を計算し、ハイライトは無視します。humanize_labels: false がないと、Potato はコードの各単語を大文字にして「Reuse Of Libraries」と表示します。adjudication ブロックは、両方のコーダーがコーディングしたすべての抜粋について、ユーザー lead を裁定者にします。
より大きなコーパスでは、両方のコーダーが抜粋の標本をコーディングし、残りの抜粋を二人のコーダーで分け合う設計がよく使われます。上の設定の num_annotators_per_item: 2 を次の行に置き換えると、各インタビューの中から抽出した 30% の標本を、両方のコーダーがコーディングします。
num_annotators_per_item:
default: 1
overlap_sample:
fraction: 0.3
count: 2
stratify_by: interview
seed: 11
assignment_strategy: randomコーダーが二人のときは、assignment_strategy: random を維持してください。Potato のデフォルトである fixed_order の割り当てでは、この標本と二人のコーダーでのテストで、52 件の抜粋すべてが最初のコーダーに割り当てられました。二人目のコーダーには、最初のコーダーがまだコーディングしていない、標本外の 26 件の抜粋が届き、それら 26 件は二重にコーディングされました。ランダムな割り当てでは、二人のコーダーはそれぞれ 34 件の抜粋をコーディングし、これは、15 件の標本と、その他の 37 件の抜粋が必要とする数より、合計で 1 件多い数です。これらの数は Potato 2.12.1 のものです。Potato 2.13.1 は assignment_hold_minutes を追加しており、仕事がなくなったコーダーに、もう一人のコーダーがまだ手を付けていない抜粋を、共有するのではなく割り当てます(タスク割り当て)。
抜粋のコーディング
プロジェクトのフォルダーからサーバーを起動します。
potato start config.yaml -p 8000各コーダーは http://localhost:8000 を開き、ユーザー名とパスワードで登録して、最初の抜粋から始めます。別のコンピューターのコーダーには、そのコンピューターから届くアドレスでサーバーが必要で、これは VPS への Potato のデプロイで説明されています。各抜粋について、コーダーは当てはまるすべてのコードにチェックを付けます。次に、「Highlight the words that show each code you ticked」の下でコードをクリックし、回答内の語句をドラッグして選択します。ハイライトは、ドラッグした文字ちょうどを覆い、単語の境界には合わせられません。「Next」をクリックすると抜粋が保存されます。
このページの裏付けとなったテスト実行
このページの数値は、動作中の Potato 2.12.1 サーバーを使って作業した二人のスクリプト化されたコーダーによるもので、各コーダーはアノテーションページが送るのと同じリクエストで各抜粋を保存しました。エクスポートと一致度レポートは、その後、保存されたコーディングに対して Potato 2.13.1 で再実行しました。最初のコーダーのコードは、各回答を丁寧に読んで作られ、コードごとに一つのハイライト句がありました。二人目のコーダーのコードは独立に書かれ、不確かな回答で異なっており、二人目のコーダーは文全体をハイライトしました。したがって、アルファの値は、シミュレートされた二人のコーダーを表すものであり、実際のコーダーでこのコードブックの信頼性がどうなるかについては何も述べていません。ブラウザでの確認では、手で引いたハイライトが、スクリプトが使ったものと同じ回答テキストへのオフセットで保存されることを確かめました。
信頼性エクスポートによる Krippendorff のアルファ
両方のコーダーが終了したら、信頼性エクスポートを実行します。
python -m potato.export --config config.yaml --format reliability --output export/コマンドは export/reliability.csv と export/reliability.md を書き出します。Markdown ファイルは、方法のセクションに貼り付けられる表です。
| Variable | Level | Krippendorff's α | 95% CI | % agreement | Units | Coders |
|---|---|---|---|---|---|---|
| codes | masi | 0.677 | [0.58, 0.764] | 53.846 | 52 | 2 |
| quotes | positional | 0.284 | [0.225, 0.346] | 75.404 | 46 | 2 |
Intervals: percentile bootstrap over units, 1000 resamples.表には質問ごとに一行があります。quotes の行は Potato 2.13.1 で新しく追加されたもので、その行については下のハイライトされた語句のセクションで説明します。Potato 2.12.1 は、スパン質問を表から除外していました。Potato は、各抜粋について各コーダーが選んだコードの集合に対して、MASI 距離を用いて Krippendorff のアルファを計算します(参考文献 3)。MASI は、二つの集合が重なるときに部分的な得点を与えます。{Funding, User community} と {Funding} を選んだ二人のコーダーは、共通のコードがない二人のコーダーより多くの得点を得ます。区間は、固定シードで抜粋を 1,000 回リサンプリングするパーセンタイル・ブートストラップです。一致率 53.846 は、両方のコーダーが同じコードの集合を選んだ場合にのみ、その抜粋を一致と数えるもので、52 件の抜粋のうち 28 件がその基準を満たしました。
方法のセクションでは、結果を一文で報告できます。たとえば、「二人のコーダーが 52 件のすべての抜粋を独立にコーディングした。抜粋ごとのコードの集合に対する MASI 距離を用いた Krippendorff のアルファは 0.677 であった(95% ブートストラップ区間 0.58 から 0.764)」のようにします。内容分析の慣例的な閾値は、変数に依拠するには 0.800、暫定的な結論には 0.667 で、二つの閾値の読み方はアノテーター間一致度で説明されています。
管理ダッシュボードは、コーディングの進行中にも同じ係数を表示します。http://localhost:8000/admin/iaa を開き、Potato がプロジェクトのフォルダーの admin_api_key.txt に書き込む管理者キーを入力します。テスト実行では、このページは alpha_masi を 0.677、平均 Jaccard を 0.788 と報告しました。Potato 2.13.1 は 0.6 から 0.8 の値を「substantial」、0.8 を超える値を「strong」と表示しますが、Potato 2.12.1 は 0.6 以上のすべての値を「strong agreement」と呼んでいました。上の内容分析の閾値は、より高い基準を設けています。
コードごとのアルファ
多くの質的研究の方法のセクションは、各コードを各抜粋での有無として採点し、コードごとに信頼性を報告します。Potato 2.13.1 はコードごとのアルファを報告しないため、CSV エクスポートからご自身で数値を計算してください。下のスクリプトは、信頼性エクスポートが使うのと同じアルファ関数を、名義尺度で呼び出します。
"""Krippendorff's alpha for each code, scored as present or absent per excerpt.
Usage: python alpha_by_code.py export/annotations.csv
"""
import csv
import sys
from collections import defaultdict
from potato.server_utils.iaa.alpha import krippendorff_alpha
chosen = defaultdict(dict) # excerpt -> coder -> set of codes
for row in csv.DictReader(open(sys.argv[1], encoding="utf-8")):
chosen[row["instance_id"]][row["user_id"]] = {
col[len("codes."):] for col, value in row.items()
if col.startswith("codes.") and value}
both = {unit: by for unit, by in chosen.items() if len(by) == 2}
codes = sorted(set().union(*(c for by in both.values() for c in by.values())))
print("code,alpha,either_coder,both_coders")
for code in codes:
rows = [(coder, unit, int(code in c)) for unit, by in both.items() for coder, c in by.items()]
either = sum(any(code in c for c in by.values()) for by in both.values())
agreed = sum(all(code in c for c in by.values()) for by in both.values())
print(f"{code},{krippendorff_alpha(rows, level='nominal'):.3f},{either},{agreed}")CSV をエクスポートして、スクリプトを実行します。
python -m potato.export --config config.yaml --format csv --output export/
python alpha_by_code.py export/annotations.csvテスト実行では、次の値が得られました。ここではアルファの順に並べています。
| コード | アルファ | いずれかのコーダーがそのコードを付けた抜粋 | 両方のコーダーが付けた抜粋 |
|---|---|---|---|
| Testing | 1.000 | 6 | 6 |
| Funding | 0.945 | 12 | 11 |
| Documentation | 0.913 | 7 | 6 |
| No code applies | 0.913 | 7 | 6 |
| Reuse of libraries | 0.880 | 5 | 4 |
| Code design | 0.854 | 9 | 7 |
| Software decay | 0.772 | 13 | 9 |
| User community | 0.752 | 16 | 11 |
| More than one maintainer | 0.681 | 12 | 7 |
| Public source code | 0.565 | 9 | 4 |
「Public source code」が 0.667 を下回るのは、一方のコーダーが、参加者が GitHub に言及するたびにこのコードを付けたためです。「More than one maintainer」と「User community」はどちらも 0.800 を下回り、この二つのコードは、参加者が他の人々がソフトウェアを生き延びさせていると述べるたびに重なります。「Reuse of libraries」のように五件の抜粋に付けられたコードは、不一致が一つあるだけで大きく動くため、コードごとの値は二つの件数の列と合わせて読んでください。
ハイライトされた語句の一致度
スパン質問について、Potato 2.13.1 の管理ページは、トークン単位の kappa、完全一致と部分一致でのスパン F1、positional_alpha という名前の文字単位のアルファ、Mathet のガンマを報告します。いずれかのコーダーがハイライトした 46 件の抜粋について、このページは、トークン単位の kappa を 0.296、完全一致のスパン F1 を 0、部分一致のスパン F1 を 0.837、positional_alpha を 0.183、ガンマを 0.575 と報告しました。完全一致の F1 が 0 なのは、一方のコーダーのハイライトが、もう一方のコーダーのハイライトと同じ文字で始まり同じ文字で終わることが一度もなかったためです。信頼性エクスポートの quotes の行が 0.284 なのは、エクスポートがすべての抜粋の文字を一つのアルファにまとめるのに対し、管理ページは抜粋ごとのアルファを平均するためです。2.12.1 では、検索のエラーのため、スパンの行は n/a で 0 項目と表示されていました。このサイトのスパン一致度計算ツールは、他の一致規則でのスパン F1 と文字単位のアルファを、ブラウザ内で計算します。計算ツールは、項目、アノテーター、ラベル、開始、終了を持つ、ハイライトごとの一行を受け取り、引用レポートにはそれらのフィールドがすべてあります。
python -m potato.export --config config.yaml --format quotation_report --output export/コマンドは export/quotations.csv を書き出し、ハイライトごとに一行で、引用、開始と終了のオフセット、抜粋、コーダーを含みます。
positional_alpha(Potato 2.12.1 では krippendorff_alpha_u という名前でした)は文字単位のアルファであり、Krippendorff の単位化アルファではありません。Potato は、回答の各文字に、その文字を覆うコードの集合を与え、文字に対して名義尺度のアルファを実行し、抜粋にわたって平均します。質的コーダーは、同じ語句に二つのコードを付けることがよくあり、2.13.1 からは、二つのコードを持つ文字は、そのうちの一つだけを持つ文字とは異なる値として数えられます。Potato 2.12.1 は、共有された文字について、長い方のハイライトのコードだけを残していました。スパンの尺度はスパンの一致度で説明されています。方法のセクションでは、抜粋のコードについてアルファを報告し、ハイライトは引用の証拠として扱ってください。
不一致の調整
アルファは、二人のコーダーの独立したコーディングを表します。誰かが不一致を調整する前の、現状のコーディングからのアルファを報告してください。最終的なコードを作るには、リードがユーザー名 lead で登録した後、http://localhost:8000/adjudicate を開きます。キューには、二人のコーダーが異なるコードの集合を選んだすべての抜粋が並びます。テスト実行では、キューに 24 件の抜粋がありました。各抜粋について、ページは両方のコーダーのコードとハイライト、最終的な集合を記録するための各コードのチェックボックス、確信度、メモ、Potato のデフォルトの一覧からの誤りカテゴリーを表示します。別のチェックボックスで、その抜粋をコードブックの変更対象としてフラグ付けします。
テスト実行では、リードは 11 件の不一致をコーダーの誤り、10 件をコードブックの欠落、2 件をテキストの曖昧さ、1 件を主観的な不一致とタグ付けしました。二件の抜粋はコードブックの変更対象としてフラグ付けされました。一つのフラグは、「Public source code」を、公開コードを持続可能性の条件として挙げる回答に絞り込むものです。もう一つのフラグは、参加者が習得しやすく動かしやすいソフトウェアについて述べているのにそのテーマを覆うコードがないため、ユーザビリティのコードを求めるものです。
判断をエクスポートします。
python -m potato.export --config config.yaml --format adjudication --output export/コマンドは、裁定された抜粋ごとに一行を持つ export/adjudicated.csv と、メモ、誤りカテゴリー、コードブックのフラグを持つ export/adjudication_log.jsonl を書き出します。adjudicated.csv は、キューにあった 24 件の抜粋だけを対象とします。三つ目のスクリプトは、裁定されたコードを、両方のコーダーが一致したコードと組み合わせます。
"""One final set of codes per excerpt: the adjudicated set where the coders
disagreed, and the coders' shared set everywhere else.
Usage: python final_codes.py export/annotations.csv export/adjudicated.csv > final_codes.csv
"""
import csv
import json
import sys
from collections import defaultdict
chosen = defaultdict(list)
for row in csv.DictReader(open(sys.argv[1], encoding="utf-8")):
chosen[row["instance_id"]].append(
{col[len("codes."):] for col, v in row.items() if col.startswith("codes.") and v})
resolved = {row["instance_id"]: set(json.loads(row["value"]))
for row in csv.DictReader(open(sys.argv[2], encoding="utf-8"))
if row["schema"] == "codes"}
out = csv.writer(sys.stdout)
out.writerow(["excerpt", "codes", "source"])
for excerpt, sets in sorted(chosen.items()):
if excerpt in resolved:
out.writerow([excerpt, "; ".join(sorted(resolved[excerpt])), "adjudicated"])
elif all(s == sets[0] for s in sets):
out.writerow([excerpt, "; ".join(sorted(sets[0])), "agreed"])
else:
out.writerow([excerpt, "", "NOT RESOLVED"])テスト実行では、final_codes.csv は 52 行で、28 件が一致、24 件が裁定でした。コードブックを変更した後は、最初のラウンドのアルファは、チームが使っているコードブックを表さなくなります。両方のコーダーに、改訂したコードブックで新しい抜粋の集合をコーディングさせ、そのラウンドからのアルファを報告してください。裁定の設計については、裁定と不一致の扱いがさらに詳しく扱っています。
REFI-QDA プロジェクトファイルのエクスポート
REFI-QDA は、NVivo、ATLAS.ti、MAXQDA、QualCoder が読み込む交換標準で、.qdpx ファイルにはプロジェクトのテキスト、コード、コーディングが含まれます。コーディング済みのプロジェクトをエクスポートします。
python -m potato.export --config config.yaml --format qdpx --output export/コマンドは export/Research_software_sustainability_interviews.qdpx を書き出します。テスト実行では、ファイルには次のものが含まれていました。
- 抜粋ごとに一つ、52 件のテキストソース
- 定義付きの十個のコード
- ユーザーとしての両方のコーダー
- それぞれにハイライトを付けたコーダーを持つ、154 件のハイライト
- 抜粋全体に適用された 167 件のコード
ファイルには両方のコーダーのコーディングが含まれており、裁定されたコードはファイルに含まれません。
Potato 2.13.1 からは、ファイルは REFI-QDA のプロジェクトスキーマに対して検証を通ります。2.12.1 では、プロジェクトにハイライトと抜粋全体のコードの両方があると、ファイルがスキーマ検査に失敗しました。Potato が各コーダーのハイライトとコードを順番に書き出していたためで、スクリプトで各ソースの要素を並べ替える必要がありました。
ファイル内のすべてのハイライトと抜粋全体のコードは、それを付けたコーダーを指定します。2.12.1 では、抜粋全体のコードにコーダーが指定されていませんでした。potato import が .qdpx ファイルをどう読み込むかは、プロジェクトのインポートで説明されています。ファイルを potato import -i Research_software_sustainability_interviews.qdpx -o reimport で Potato 2.13.1 に再インポートすると、52 件のテキストと、同じオフセットの 154 件すべてのハイライトが得られ、次の損失がありました。
- ハイライトは、すべてのコーダーに対する提案として取り込まれます。各ハイライトは、コーダーの名前を
annotatorフィールドに保持しますが、これは Potato 2.12.1 では失われていました。 - 抜粋全体のコードは、各項目の
document_codesフィールドとして取り込まれ、このフィールドを読む質問はありません。 - エクスポートは回答テキストだけを書き出すため、インタビュアーの質問とインタビュー番号は残りません。
- コードの定義は、各スパンラベルの
descriptionとして取り込まれ、スパン質問はdescriptionを表示しません。
チームでのコーディングのための他のツール
NVivo のコーディング比較クエリは、二人のユーザーまたはユーザーグループの間で、各ファイルの各コードについて Cohen の kappa と一致率を報告します。NVivo は、テキストの文字数で一致を数えます。ATLAS.ti のコーダー間一致度ツールは、コーダーのプロジェクトを統合した後で、一致率、Holsti 指数、Krippendorff のアルファ系の係数を報告し、ATLAS.ti のマニュアルは、Cohen の kappa は意図的に除外したと述べています。MAXQDA は、文書レベルでは一致率と偶然補正された kappa を、セグメントレベルでは Brennan と Prediger の kappa を報告します。セグメントレベルでは、コーディングがデフォルトで少なくとも 90% 重なる場合に、二つのコーディングが一致します。Dedoose の Testing Center は、コーダーのコード適用を、Cohen の kappa を使って専門家のものと比較します。QualCoder は無料のデスクトッププログラムで、Cohen の kappa でコーダーを比較します。これらのツールはどれも、テキストに加えて音声、動画、PDF をコーディングでき、すでにそのツールで作業しているチームに適しています。
Potato は、チームが管理するサーバー上の無料のツールで、区間付きのアルファを求め、デスクトップへのインストールなしにブラウザでコーディングしたいチームに適しています。質的データ分析ソフトウェアの比較は、各ツールの価格、ホスティング、AI 機能を一覧にしています。
チームでのコーディングにおける Potato の限界
- テキストのみ。 Potato はテキストをコーディングし、REFI-QDA インポーターもテキストソースだけを読み込みます。
potato transcripts --transcribe --diarizeは、まず録音を記録に変換します。 - エクスポートにコードごとのアルファがありません。
reliabilityエクスポートは質問ごとに一行を出力し、コードごとのアルファには上のスクリプトが必要です。 .qdpxファイルでは抜粋ごとに一つのソース。 抜粋ごとにコーディングされたプロジェクトは、六つのインタビューではなく、回答ごとに一つ、NVivo や ATLAS.ti では 52 件のソースになります。.qdpxファイルには両方のコーダーの生のコーディング。 裁定されたコードはadjudicated.csvにのみ出力されます。
次に読むもの
- QDA モード - チームでのコーディングの前に、一人のアナリストでコードブックを作るために
- 内容分析 - ファイルから読み込むコードブックと、信頼性の表の列について
- アノテーター間一致度 - 一致度の係数の選び方と読み方について
- スパンの一致度 - ハイライトされた語句に合う尺度について
- 裁定と不一致の扱い - 裁定の設計について
- 一致度計算ツール - 任意のツールからエクスポートしたコードの CSV から、アルファと kappa を求めるために
- Potato での質的研究 - 質的研究向けの機能を一か所にまとめたもの
- 質的研究におけるコーダー間信頼性
- 質的コーディングのためのインタビュー記録の準備
参考文献
- Rosado de Souza, M., Haines, R., Vigo, M., & Jay, C. (2019). What Makes Research Software Sustainable? An Interview Study with Research Software Engineers. 2019 IEEE/ACM 12th International Workshop on Cooperative and Human Aspects of Software Engineering (CHASE), 135-138. https://doi.org/10.1109/CHASE.2019.00039
- de Souza, M. R., Haines, R., Vigo, M., & Jay, C. (2019). What makes research software sustainable? Anonymized interview transcripts [Data set]. Zenodo. https://doi.org/10.5281/zenodo.1345067
- Passonneau, R. (2006). Measuring Agreement on Set-valued Items (MASI) for Semantic and Pragmatic Annotation. Proceedings of the Fifth International Conference on Language Resources and Evaluation (LREC'06). https://aclanthology.org/L06-1392/