

# 指定したX投稿サンプルでキーワードの共起を測定する方法

指定したサンプルのうち、本文が完全な投稿ごとに、対象語と相手語の有無を1回ずつ数えます。次に、対象語を含む投稿で相手語が出現する割合と、対象語を含まない投稿で相手語が出現する割合を比較します。

ここでいう語とは、集計前に選んだ単語です。対象語とは、着目する単語です。相手語とは、対象語との組み合わせを調べるもう1つの単語です。語のペアとは、この2つの語の組み合わせです。共起とは、両方の語が同じ投稿に出現することです。集計対象の投稿とは、集計範囲内にあり、本文が完全で、重複していない投稿です。集計範囲は、対象期間と、個々のURLを明記したリストで定めます。

共起件数とは、集計対象の投稿のうち、両方の語を含む投稿の件数です。条件付き出現割合は、共起件数を対象語を含む投稿の件数で割った値です。背景群での出現割合は、対象語を含まない投稿のうち相手語を含む投稿の件数を、対象語を含まない投稿の総件数で割った値です。分母とは、割り算で割る側の数です。分母がない割合は定義できません。

結果として、語の有無フラグ、語のペアの集計表、2つの出現割合、本文の欠損を記録した台帳が得られます。台帳とは、集計から除外した取得試行を保存した一覧です。結果の説明は、指定したこのサンプルだけを対象にしてください。

## 1. 集計範囲を定める

投稿を収集する前に、対象語と各相手語を記録してください。対象に含める投稿の公開日を記録してください。集計範囲を構成する既知のURLを、個々に正確に記録してください。

この集計で分かるのは、指定したサンプルで、どの相手語が対象語と共起するかです。時間の経過に沿った使用履歴を作成するものではありません。X上のすべての投稿を対象とする検索サービスでもありません。

これらの選択を先に記録してください。投稿の語を見てから相手語を選ぶと、すでに気づいたパターンに都合のよい選択をするおそれがあります。

## 2. URLが既知の公開投稿を収集する

Actorとは、ソースからデータ行を収集する、ホスト環境で動作するプログラムです。Taskとは、Actor用に保存した入力設定です。実行とは、Actorを1回動かすことです。

[X Post Metrics](https://apify.com/chronometrica/x-post-metrics) Actorの公開ビルド1.0.4を使用してください。現在のTaskは[X Post Analytics Snapshot](https://apify.com/chronometrica/x-post-metrics/examples/x-post-analytics-snapshot)です。このTaskは、開始時の入力設定を保存しています。語の集計を代わりに行うものではありません。Taskが保存されていることは、集計が自動で行われる証拠にはなりません。

このビルドは`startUrls`を読み取ります。各値には、`/status/`を含む、既知の公開投稿URLを指定する必要があります。保存済みのリストには、次の3つのサンプルURLがあります。

- https://x.com/OpenAI/status/2074907025537224840
- https://x.com/OpenAI/status/2074907027378511884
- https://x.com/OpenAI/status/2074907031862190406

リスト全体を、すでに把握している公開投稿の`/status/` URLを1つだけ指定したものに置き換えてください。初回の実行には、その1つのURLを使ってください。検索を追加しないでください。投稿履歴を要求しないでください。`maxItems`を設定しないでください。このActorは、完全なアーカイブを返すものではありません。ほかの既知のURLを追加するのは、最初の行を確認してからにしてください。

保存される各行には、次のフィールドを格納できます。

| フィールド | 格納する内容 |
| --- | --- |
| `inputUrl` | 送信したURL |
| `postUrl` | その行に記録された投稿URL |
| `postId` | 投稿ID |
| `postType` | 投稿の種類 |
| `publishedAt` | 公開日時 |
| `text` | 現在の投稿本文 |
| `profileUrl` | プロフィールURL |
| `profileId` | プロフィールID |
| `profileUsername` | プロフィールのユーザー名 |
| `profileName` | プロフィールの表示名 |
| `status` | その行の状態 |
| `statusReason` | その状態になった理由 |
| `observedAt` | その行のデータを観測した日時 |

`text`がnullになることがあります。その行のほかの項目も、nullになることがあります。nullは、値が欠損していることを意味します。件数が0という意味ではありません。

`postMetricStatus`は`text`とは別の情報です。6つの指標それぞれに1つの項目があります。指標は、表示回数、いいね数、返信数、リポスト数、引用数、ブックマーク数です。各項目には、それぞれの状態と精度があります。精度とは、その指標の値がどれほど正確かを示すものです。6つの項目を、1つの尺度の6段階と解釈しないでください。これらは、本文が完全であることを証明するものではありません。

OUTPUTは、実行についての証拠です。語の集計表ではありません。`inputCount`、`datasetRows`、`usefulRows`、`billableRows`、`failedRows`、`statusCounts`、`stopReason`が記録されます。`inputCount`は、その実行が受け取ったURLの数です。`datasetRows`は、保存した行数です。`usefulRows`は、その実行で有用とされた行の合計数です。`billableRows`は、その実行で課金対象となった行の合計数です。`failedRows`は、その実行で失敗した行の合計数です。`statusCounts`は、行を状態別に集計したものです。`stopReason`は、実行が停止した理由を示します。これらの合計値は、各行にあるフィールドではありません。

URLが既知のOpenAIの公開投稿1件を読み取り、結果を確認したところ、正しい投稿IDとプロフィールIDが返されました。公開日時と現在の各カウント値も返されました。本文は存在し、空ではありませんでした。本文は200文字でした。この記事には、その本文を転載していません。この確認でのOUTPUTは、`inputCount`が1、`datasetRows`が1、`usefulRows`が1、`billableRows`が1、`failedRows`が0でした。`statusCounts`はokが1でした。`stopReason`は`inputs_exhausted`でした。

この結果は、URLが既知の公開投稿1件で本文を取得できたことを示します。すべてのURLで同じ結果になることを証明するものではありません。画像内の文字を読み取ったことも証明しません。引用先の投稿本文、リンク先のページ、動画内の発話を読み取ったことも証明しません。非表示の部分やアクセスが制限された部分は、別途確認する必要があります。状態がokであっても、集計に必要な本文が十分にあることは証明できません。本文が200文字あっても、その行に投稿全文が格納されていることは証明できません。

1つの投稿を1つの単位として扱うため、`postId`で行を照合してください。`publishedAt`と`observedAt`を保持してください。投稿IDが欠損している場合は、その取得試行に専用の状態を付けてください。ソースからの取得に失敗した場合も、その取得試行に専用の状態を付けてください。集計範囲に日付を使う場合、`publishedAt`が不明な投稿は、対象期間内の日付が確認できた投稿には当たりません。日付が判明するまで、その取得試行を期間限定の集計から除外してください。情報の欠損を、語の出現件数が0であることに置き換えないでください。

## 3. 本文が完全かどうかを判断する

この分析では、投稿本文だけを使います。各行について、集計に必要な本文が十分にそろっているかを記録してください。その記録を保存してください。

状態がokであることを、本文が完全である証拠として扱わないでください。`postMetricStatus`も、その証拠として扱わないでください。`text`が欠損している場合や、一部しかない場合は、その投稿を完全な本文がある投稿の分母から除外してください。別に入手した本文を追加するのは、その本文を自分で確認してからにしてください。

画像から語を取り込まないでください。リンク先のページから語を取り込まないでください。動画から語を取り込まないでください。行の状態が成功を示していても、本文が十分かどうかは未確認のままの場合があります。

`text`フィールドには、`observedAt`の時点で観測した文面が入ります。投稿が編集されていれば、以前の文面と異なる場合があります。一部が欠けている場合もあります。その違いが集計を変える場合は、現在の本文と以前の本文を分けて保持してください。扱い方を文書に記録せずに、両者を統合しないでください。

## 4. 集計前に語の一致ルールを記録する

文字列の一致ルールを1つに定め、最初のフラグを付ける前に記録してください。この記事の英語の例では、次のルールに固定します。

大文字と小文字を区別しません。単語全体が一致する場合だけを数えます。単語全体とは、両側に単語の境界があるもの、または本文の先頭や末尾にあるものです。境界とは、単語の区切りです。空白は境界になります。ピリオド、コンマ、引用符も境界になります。これらの記号は単語の一部ではありません。このルールでは、文字列timer.は、語timerに一致します。

語幹処理は行わないでください。語幹とは、単語を短くした基本部分です。類義語を同じ語として数えないでください。元の本文は変更せずに保持してください。2語以上の句には、専用のルールを文書で定める必要があります。別の文字体系にも専用のルールが必要です。リンクや別名にも専用のルールが必要です。そのルールを使う前に、元の本文で検証してください。

単語全体が一致しても、投稿者がその語の表すものを支持しているとは限りません。また、[その語が現実の何を指しているか](/ja/articles/x%E6%8A%95%E7%A8%BF%E3%81%AE%E8%A3%BD%E5%93%81%E8%A8%80%E5%8F%8A%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)を証明するものでもありません。

## 5. 集計対象の投稿ごとにフラグを付ける

二値フラグとは、1または0の値です。集計対象の本文に、定めたルールに従って語が含まれる場合は1にします。完全な本文にその語が含まれない場合は0にします。重複を除いた集計対象の各投稿に、語ごとに1つのフラグを付けてください。

集計の単位は投稿です。1つの投稿に同じ語が5回出現しても、フラグは1のままです。この繰り返しは、投稿内の書き方を表すものです。投稿の件数は増えません。同じエクスポートデータがまったく同じ内容で重複していても、投稿の件数は増えません。

同じ投稿の2つの版で内容が異なる場合は、集計前に採用するソースを選んでください。その選択を記録してください。変更が生じた分母も記録してください。両方の版を2件の投稿として扱わないでください。

## 6. 2×2表を作る

相手語を1つ選び、集計対象のすべての投稿を4つのセルに分類します。セルとは、4つの件数のいずれかを示す区画です。分類は、両方の語を含む、対象語だけを含む、相手語だけを含む、どちらの語も含まない、の4つです。

n、対象語を含む投稿件数、相手語を含む投稿件数、共起件数を報告してください。nは、集計対象の投稿件数です。

次の単純な式を使います。

条件付き出現割合 = 共起件数 / 対象語を含む投稿件数

背景群での出現割合 = 対象語を含まず相手語を含む投稿件数 / 対象語を含まない投稿件数

条件付き出現割合とは、対象語を含む投稿のうち、相手語を含む投稿の割合です。背景群での出現割合とは、対象語を含まない投稿のうち、相手語を含む投稿の割合です。

対象語を含む投稿件数が0の場合、条件付き出現割合は定義できません。対象語を含まない投稿件数が0の場合、背景群での出現割合は定義できません。割合は空欄にしてください。空欄を埋めるために0を記入しないでください。0と記入すると、投稿が存在しない群で測定したと主張することになります。

## 7. 分母を踏まえて割合を比較する

両方の割合を分数で示してください。条件付き出現割合が大きくても、単によく使われる語である可能性があります。背景群での出現割合は、その可能性を示します。共起件数が多いことは、特定の結び付きがある証拠にはなりません。

このサンプルは小さく、URLも自分で選んだものです。X全体を代表することはできません。因果関係を示すこともできません。X上でその語を使う投稿が何件あるかも分かりません。パターンがどの程度の速さで変わるかも分かりません。統計的有意性も示せません。統計的有意性とは、結果が偶然に生じたものかどうかを正式な検定で判断することに関わる用語です。この表は、その検定ではありません。

投稿者は、その語の表すものを支持せずに語を引用している場合があります。意味の確認は別の作業です。これらの割合は、今回の集計対象の投稿を記述するために使ってください。

## 8. 集計を保存し、限界を明記する

語の有無フラグ、語のペアの集計表、文書化したルール、除外台帳を保存してください。これらを保存して初めて、読者は各分母を再現できます。

期間を通じて条件に一致するすべての投稿が必要な場合は、このサンプルでは何ができないかを明記してください。既知のURLのリストは、その全件集合ではありません。サンプルを使って、明示した考えを検討してください。その後、文書化した集計範囲を改善してください。この表を、X全体の傾向として提示しないでください。

## 同じルールを独自に作成した架空の例に適用する

ここからは、独自に作成した架空の例です。以下の投稿、ID、件数は、学習用の例です。Actorの結果ではありません。OUTPUTでもありません。X上の言語使用を推定するものではありません。因果関係を示すものでもありません。

各投稿には、重複しない架空のIDと、上記のルールに照らして完全な本文があります。これらのIDは、実際のX投稿IDではありません。大文字と小文字は区別しないため、Jobはjobに一致します。文末のピリオドは境界です。Jobは先頭にあるため、本文の先頭が境界になります。ここには、retry、timer、jobが長い単語の一部として含まれているだけの単語はありません。

| ID | 現在の架空の本文 | retry | timer | job |
| --- | --- | --- | --- | --- |
| F1 | Job retry uses a timer.（ジョブの再試行ではタイマーを使います。） | 1 | 1 | 1 |
| F2 | Job retry checks the timer.（ジョブの再試行ではタイマーを確認します。） | 1 | 1 | 1 |
| F3 | Job retry waits for a timer.（ジョブの再試行ではタイマーを待ちます。） | 1 | 1 | 1 |
| F4 | Job retry cancels the timer.（ジョブの再試行ではタイマーを取り消します。） | 1 | 1 | 1 |
| F5 | Job retry adds a log.（ジョブの再試行ではログを追加します。） | 1 | 0 | 1 |
| F6 | Job retry follows the rule.（ジョブの再試行ではルールに従います。） | 1 | 0 | 1 |
| F7 | Job timer logs a message.（ジョブのタイマーはメッセージをログに記録します。） | 0 | 1 | 1 |
| F8 | Job log records a message.（ジョブのログはメッセージを記録します。） | 0 | 0 | 1 |
| F9 | Job rule records a message.（ジョブのルールはメッセージを記録します。） | 0 | 0 | 1 |
| F10 | Job workers send a message.（ジョブのワーカーはメッセージを送信します。） | 0 | 0 | 1 |

最初の四件の投稿には、retry、timer、jobがあります。次の二件にはretryとjobがありますが、timerはありません。七件目にはtimerとjobがありますが、retryはありません。最後の三件には、これらの語のうちjobだけがあります。

フラグを合計します。retryの合計は6です。timerの合計は5です。jobの合計は10です。F1、F2、F3、F4では、retryとtimerの両方が1です。共起件数は4です。

retryとtimerの表は、次のようになります。

| 対象語 | timer 1 | timer 0 | 行合計 |
| --- | --- | --- | --- |
| retry 1 | 4 | 2 | 6 |
| retry 0 | 1 | 3 | 4 |
| 列合計 | 5 | 5 | 10 |

nは10です。対象語を含む投稿件数は6です。相手語を含む投稿件数は5です。共起件数は4です。4つのセルの件数は、4、2、1、3です。

条件付き出現割合は4/6です。この分数を丸めると66.7%になります。分母は、retry 1の行にある6件の投稿です。4を全10件の投稿で割らないでください。

背景群での出現割合は1/4で、25%です。分母は、retry 0の行にある4件の投稿です。その行でtimerを含むのはF7だけです。timer 0の列合計は5です。これは別の合計です。この分母に5を使わないでください。

retryとjobの表にも、同じ10件の投稿を使います。

| 対象語 | job 1 | job 0 | 行合計 |
| --- | --- | --- | --- |
| retry 1 | 6 | 0 | 6 |
| retry 0 | 4 | 0 | 4 |
| 列合計 | 10 | 0 | 10 |

retryとjobの共起件数は6です。条件付き出現割合は6/6で、100%です。背景群での出現割合は4/4で、100%です。jobはtimerより共起件数が多くなっています。timerは4件です。jobは6件です。jobの2つの割合は等しいため、この例ではjobに群間の差は見られません。0のセルは、完全な本文で語が実際に存在しないことを示します。本文の欠損ではありません。

ソースからの取得を試みたものが、さらに2件ありますが、本文がありません。読者が確認できる台帳に残してください。これらをF11、F12と呼ばないでください。どちらの語も含まないセルに入れないでください。この台帳をOUTPUTに転記しないでください。`failedRows`として扱わないでください。本文が欠損していれば、語の有無は不明です。語がないことを示すフラグにはなりません。語が見当たらないことから、取得元の処理が失敗したと推定することもできません。

| 取得試行 | 本文 | retry | timer | job | 集計対象 | 理由 |
| --- | --- | --- | --- | --- | --- | --- |
| S1 | 取得できず | 不明 | 不明 | 不明 | 対象外 | 本文が欠損しているため、すべてのフラグが不明です。この取得試行を、語を含まない投稿として扱うことはできません。 |
| S2 | 取得できず | 不明 | 不明 | 不明 | 対象外 | 本文が欠損しているため、すべてのフラグが不明です。この取得試行を、語を含まない投稿として扱うことはできません。 |

収集では、ソースからの取得を12件試みています。10件は、本文が完全で、重複のない集計対象の投稿です。2件は本文を取得できていません。完全な本文がある投稿の分母は、10のままです。

対象語を含む群の集計対象投稿が0件であれば、条件付き出現割合は定義できません。背景群の投稿が0件であれば、その割合も定義できません。「定義できない」と記載してください。0%という値を作らないでください。

この例に限って、4/6と1/4を並べて解釈してください。この差が記述するのは、これら10の文だけです。X全体を記述するものではありません。因果関係、有意性、傾向を示すものでもありません。jobの例からは、2つ目の割合が必要な理由が分かります。jobは共起件数がより多い一方で、2つの割合はどちらも100%です。

## 次に行うこと

明示した語の一致ルールを、確認済みの本文に適用してください。二値フラグ、語のペアの集計表、除外台帳を保存してください。条件付き出現割合と背景群での出現割合を比較してください。両方の分母を示してください。[X Post Metrics](https://apify.com/chronometrica/x-post-metrics) Actorと[X Post Analytics Snapshot](https://apify.com/chronometrica/x-post-metrics/examples/x-post-analytics-snapshot) Taskを使用してください。集計前に、保存済みの`startUrls`リストを、既知の公開投稿の`/status/` URLを1つだけ指定したものに置き換えてください。

## 出典と参考資料

- [X Post Metrics Actor](https://apify.com/chronometrica/x-post-metrics)
- [X Post Analytics Snapshot Task](https://apify.com/chronometrica/x-post-metrics/examples/x-post-analytics-snapshot)