kur0cky

こんにちは

gt パッケージの紹介 ~Rで作表の決定版!?~ (2)

Rで綺麗な表を作成するgtパッケージ紹介の第2段です。

前回の記事では、gtパッケージの概要と作表の大まかな流れを紹介しました。 kur0cky.hatenablog.com

今回は、実際に表をカスタマイズするときに使う様々な関数を整理し、より細かな作業を紹介します。

gtパッケージの関数群の整理

公式のリファレンスに整理されていることではありますが、gtパッケージの関数はいくつかのグループに分けることができます。 本記事では特に、gtテーブルの各パーツ(ヘッダやレコードのグルーピングなど)を作成するfmt_**()関数を中心に紹介します。

  • gt(), gt_preview()
    • gt_tblオブジェクトの作成。gt_preview()では先頭と末尾を(デフォルトでは)5行ずつ表示するオブジェクトを作成します。
  • tab_***()
    • 前の記事で紹介したgtの表の各要素を追加するような関数群です。たとえば、ヘッダーやフッターの作成、行や列ごとのグルーピングを行うことができます。
  • fmt_***()
    • セルの値の見栄えをよくするような関数群です。たとえば、datetimeのフォーマットを一括で修正したり、欠損NA-で一括置換することができます。
  • cols_***()
    • カラム(変数)全体の変更を行うような関数群です。たとえば、カラムの順序を入れ替えたり名前の変更、2つのカラムの結合などを行うことができます。
  • 行変更関数:
    • 現在はテーブル内の任意の行グループの順序を変更することができるrow_group_order()や、集計行を追加するsummary_rows(), grand_summary_rows()があります。
  • ***_image()
    • gtパッケージでは表のセル中に画像を挿入することができます。なんとggplotオブジェクトもggplot_image()で入れることができます。
  • opt_***()
    • よく使われる表オプションを簡単に設定することができます。たとえば、 脚注で使うマークのセットを変更したり、行の縞模様を有効にしたり、表ヘッダのアラインメントを変更したりすることができます。
  • info_***
    • 有用な情報を含むgtテーブルを表示してくれる関数群です。gtがサポートする日付スタイルや時刻スタイル、カラーパレット、通貨、ロケールについての参照情報を得ることができます。ここを参照することで、たとえば表示させたいdatetimeのフォーマットなどにすぐアクセスすることができます。
  • ヘルパー関数:
    • 表内でマークダウン表記を使うためのmd()や数値をパーセンテージで扱うためのpct()など、便利な細々とした関数群です。

gtテーブルの各パーツの作成

まずはライブラリを読み込みます

library(tidyverse)
library(gt)

今回は誰もが知っているirisデータを使った、次の集計を表にしたいと思います。

df <- iris %>% 
  gather(var, value, -Species) %>% 
  group_by(Species, var) %>% 
  summarise(q1 = quantile(value, .25),
            median = median(value),
            q3 = quantile(value, .75),
            mean = mean(value),
            sd = sd(value)) %>% 
  ungroup()
df
# A tibble: 12 x 7
   Species    var             q1 median    q3  mean    sd
   <fct>      <chr>        <dbl>  <dbl> <dbl> <dbl> <dbl>
 1 setosa     Petal.Length  1.4    1.5   1.58 1.46  0.174
 2 setosa     Petal.Width   0.2    0.2   0.3  0.246 0.105
 3 setosa     Sepal.Length  4.8    5     5.2  5.01  0.352
 4 setosa     Sepal.Width   3.2    3.4   3.68 3.43  0.379
 5 versicolor Petal.Length  4      4.35  4.6  4.26  0.470
 6 versicolor Petal.Width   1.2    1.3   1.5  1.33  0.198
 7 versicolor Sepal.Length  5.6    5.9   6.3  5.94  0.516
 8 versicolor Sepal.Width   2.52   2.8   3    2.77  0.314
 9 virginica  Petal.Length  5.1    5.55  5.88 5.55  0.552
10 virginica  Petal.Width   1.8    2     2.3  2.03  0.275
11 virginica  Sepal.Length  6.22   6.5   6.9  6.59  0.636
12 virginica  Sepal.Width   2.8    3     3.18 2.97  0.322

最終的には下のようなな表を作っていきます。

Edgar Anderson's Iris Data
the most famous dataset
percentile mean sd
q1 median q3
Petal.Length
setosa 1.400 1.50 1.575 1.462 0.1736640
versicolor 4.000 4.35 4.600 4.260 0.46991101
virginica 5.100 5.55 5.875 5.552 0.55189471
Petal.Width
setosa 0.200 0.20 0.300 0.246 0.1053856
versicolor 1.200 1.30 1.500 1.326 0.1977527
virginica 1.800 2.00 2.300 2.026 0.2746501
Sepal.Length
setosa 4.800 5.00 5.200 5.006 0.3524897
versicolor 5.600 5.90 6.300 5.936 0.51617111
virginica 6.225 6.50 6.900 6.588 0.63587961
Sepal.Width
setosa 3.200 3.40 3.675 3.428 0.3790644
versicolor 2.525 2.80 3.000 2.770 0.3137983
virginica 2.800 3.00 3.175 2.974 0.3224966
Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. Annals of Eugenics, 7, Part II, 179–188.

1 標準偏差が0.4以上

gtテーブルの作成:

最も基本となる、そもそものテーブルオブジェクトの作成はgt()で行います。これだけでも十分綺麗な表が出力できています。

df %>% 
  gt()
Species var q1 median q3 mean sd
setosa Petal.Length 1.400 1.50 1.575 1.462 0.1736640
setosa Petal.Width 0.200 0.20 0.300 0.246 0.1053856
setosa Sepal.Length 4.800 5.00 5.200 5.006 0.3524897
setosa Sepal.Width 3.200 3.40 3.675 3.428 0.3790644
versicolor Petal.Length 4.000 4.35 4.600 4.260 0.4699110
versicolor Petal.Width 1.200 1.30 1.500 1.326 0.1977527
versicolor Sepal.Length 5.600 5.90 6.300 5.936 0.5161711
versicolor Sepal.Width 2.525 2.80 3.000 2.770 0.3137983
virginica Petal.Length 5.100 5.55 5.875 5.552 0.5518947
virginica Petal.Width 1.800 2.00 2.300 2.026 0.2746501
virginica Sepal.Length 6.225 6.50 6.900 6.588 0.6358796
virginica Sepal.Width 2.800 3.00 3.175 2.974 0.3224966

gt()では、行名を示すカラムのオプションrowname_col、グループを示すカラムのオプションgroupname_colなどを指定することができます。ここでは、どちらも指定してみましょう。

df %>% 
  gt(rowname_col = "Species", groupname_col = "var")
q1 median q3 mean sd
Petal.Length
setosa 1.400 1.50 1.575 1.462 0.1736640
versicolor 4.000 4.35 4.600 4.260 0.4699110
virginica 5.100 5.55 5.875 5.552 0.5518947
Petal.Width
setosa 0.200 0.20 0.300 0.246 0.1053856
versicolor 1.200 1.30 1.500 1.326 0.1977527
virginica 1.800 2.00 2.300 2.026 0.2746501
Sepal.Length
setosa 4.800 5.00 5.200 5.006 0.3524897
versicolor 5.600 5.90 6.300 5.936 0.5161711
virginica 6.225 6.50 6.900 6.588 0.6358796
Sepal.Width
setosa 3.200 3.40 3.675 3.428 0.3790644
versicolor 2.525 2.80 3.000 2.770 0.3137983
virginica 2.800 3.00 3.175 2.974 0.3224966

タイトルの設定

タイトルやサブタイトルはtab_header()で追加することができます

df %>% 
  gt() %>% 
  tab_header(title = "Edgar Anderson's Iris Data",
             subtitle = "the most famous dataset")
Edgar Anderson's Iris Data
the most famous datset
Species var q1 median q3 mean sd
setosa Petal.Length 1.400 1.50 1.575 1.462 0.1736640
setosa Petal.Width 0.200 0.20 0.300 0.246 0.1053856
setosa Sepal.Length 4.800 5.00 5.200 5.006 0.3524897
setosa Sepal.Width 3.200 3.40 3.675 3.428 0.3790644
versicolor Petal.Length 4.000 4.35 4.600 4.260 0.4699110
versicolor Petal.Width 1.200 1.30 1.500 1.326 0.1977527
versicolor Sepal.Length 5.600 5.90 6.300 5.936 0.5161711
versicolor Sepal.Width 2.525 2.80 3.000 2.770 0.3137983
virginica Petal.Length 5.100 5.55 5.875 5.552 0.5518947
virginica Petal.Width 1.800 2.00 2.300 2.026 0.2746501
virginica Sepal.Length 6.225 6.50 6.900 6.588 0.6358796
virginica Sepal.Width 2.800 3.00 3.175 2.974 0.3224966

リファレンスの追加

gtではtab_source_note()によってフッターにリファレンスを追加することができます。irisデータのソースであるFisherの論文を引用してみましょう。 また、gtテーブルの各部分では、md()によって、マークダウン記法を用いることもできます。雑誌名を斜体で、巻号を太字で書きてみます。

df %>% 
  gt() %>%
  tab_source_note(source_note = md("Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. *Annals of Eugenics*, **7**, Part II, 179–188."))
Species var q1 median q3 mean sd
setosa Petal.Length 1.400 1.50 1.575 1.462 0.1736640
setosa Petal.Width 0.200 0.20 0.300 0.246 0.1053856
setosa Sepal.Length 4.800 5.00 5.200 5.006 0.3524897
setosa Sepal.Width 3.200 3.40 3.675 3.428 0.3790644
versicolor Petal.Length 4.000 4.35 4.600 4.260 0.4699110
versicolor Petal.Width 1.200 1.30 1.500 1.326 0.1977527
versicolor Sepal.Length 5.600 5.90 6.300 5.936 0.5161711
versicolor Sepal.Width 2.525 2.80 3.000 2.770 0.3137983
virginica Petal.Length 5.100 5.55 5.875 5.552 0.5518947
virginica Petal.Width 1.800 2.00 2.300 2.026 0.2746501
virginica Sepal.Length 6.225 6.50 6.900 6.588 0.6358796
virginica Sepal.Width 2.800 3.00 3.175 2.974 0.3224966
Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. Annals of Eugenics, 7, Part II, 179–188.

列のグルーピング

gtでは変数をグルーピングすることができ、そのグループをスパナと呼びます。ここでは、第一四分位、中央値、第三四分位をパーセンタイルとしてグルーピングします。 まとめる変数の指定columnsでは、dplyrと同じように、vars()を使うことができます。

df %>%
  gt() %>% 
  tab_spanner(label = "percentile",
              columns = vars(q1, median, q3))
Species var percentile mean sd
q1 median q3
setosa Petal.Length 1.400 1.50 1.575 1.462 0.1736640
setosa Petal.Width 0.200 0.20 0.300 0.246 0.1053856
setosa Sepal.Length 4.800 5.00 5.200 5.006 0.3524897
setosa Sepal.Width 3.200 3.40 3.675 3.428 0.3790644
versicolor Petal.Length 4.000 4.35 4.600 4.260 0.4699110
versicolor Petal.Width 1.200 1.30 1.500 1.326 0.1977527
versicolor Sepal.Length 5.600 5.90 6.300 5.936 0.5161711
versicolor Sepal.Width 2.525 2.80 3.000 2.770 0.3137983
virginica Petal.Length 5.100 5.55 5.875 5.552 0.5518947
virginica Petal.Width 1.800 2.00 2.300 2.026 0.2746501
virginica Sepal.Length 6.225 6.50 6.900 6.588 0.6358796
virginica Sepal.Width 2.800 3.00 3.175 2.974 0.3224966

行のグルーピング

行のグルーピングにはtab_row_group()を用います。グループにする行の指定rowsには、数値ベクトルを指定することができますが、以下のgt(rowname_col = "Species")のように行名が指定してある場合、dplyr::select()と同様にヘルパー関数を使うことができます。便利ですね。

df %>% 
  gt(rowname_col = "Species") %>% 
  tab_row_group(group = "vからはじまる種類",
                rows = starts_with("v"),
                others = "その他")
var q1 median q3 mean sd
vからはじまる種類
versicolor Petal.Length 4.000 4.35 4.600 4.260 0.4699110
versicolor Petal.Width 1.200 1.30 1.500 1.326 0.1977527
versicolor Sepal.Length 5.600 5.90 6.300 5.936 0.5161711
versicolor Sepal.Width 2.525 2.80 3.000 2.770 0.3137983
virginica Petal.Length 5.100 5.55 5.875 5.552 0.5518947
virginica Petal.Width 1.800 2.00 2.300 2.026 0.2746501
virginica Sepal.Length 6.225 6.50 6.900 6.588 0.6358796
virginica Sepal.Width 2.800 3.00 3.175 2.974 0.3224966
その他
setosa Petal.Length 1.400 1.50 1.575 1.462 0.1736640
setosa Petal.Width 0.200 0.20 0.300 0.246 0.1053856
setosa Sepal.Length 4.800 5.00 5.200 5.006 0.3524897
setosa Sepal.Width 3.200 3.40 3.675 3.428 0.3790644

脚注の追加

tab_footnote()によって脚注を追加することができます。 どの部分に脚注をつけるかはlocationsオプションで指定しますが、ここではヘルパー関数cells_***()を使うことができます。 ここでは、標準偏差sdが0.4を超えるところに脚注をつけてみましょう。表の本体 body につけたいので、ヘルパー関数はcells_body()を使います。cells_body(columns = vars(sd), rows = sd > 0.4)としました。このように、条件で脚注をつける箇所を指定することができるため、たとえば「p値が有意となるものに印をつけたい」といった場合に非常に有用です。

df %>% 
  gt() %>% 
  tab_footnote(
    footnote = "標準偏差が0.4以上",
    locations = cells_body(
      columns = vars(sd),
      rows = sd > 0.4))
Species var q1 median q3 mean sd
setosa Petal.Length 1.400 1.50 1.575 1.462 0.1736640
setosa Petal.Width 0.200 0.20 0.300 0.246 0.1053856
setosa Sepal.Length 4.800 5.00 5.200 5.006 0.3524897
setosa Sepal.Width 3.200 3.40 3.675 3.428 0.3790644
versicolor Petal.Length 4.000 4.35 4.600 4.260 0.46991101
versicolor Petal.Width 1.200 1.30 1.500 1.326 0.1977527
versicolor Sepal.Length 5.600 5.90 6.300 5.936 0.51617111
versicolor Sepal.Width 2.525 2.80 3.000 2.770 0.3137983
virginica Petal.Length 5.100 5.55 5.875 5.552 0.55189471
virginica Petal.Width 1.800 2.00 2.300 2.026 0.2746501
virginica Sepal.Length 6.225 6.50 6.900 6.588 0.63587961
virginica Sepal.Width 2.800 3.00 3.175 2.974 0.3224966

1 標準偏差が0.4以上

組み合わせる

それでは、上記のtab_***()をブロックのように組み合わせて、冒頭の表を作ります。

df %>% 
  gt(groupname_col = "var", rowname_col = "Species") %>% 
  tab_header(title = "Edgar Anderson's Iris Data",
             subtitle = "the most famous dataset") %>% 
  tab_source_note(source_note = md("Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. *Annals of Eugenics*, **7**, Part II, 179–188.")) %>%
  tab_spanner(label = "percentile",
              columns = vars(q1, median, q3)) %>% 
  tab_footnote(
    footnote = "標準偏差が0.4以上",
    locations = cells_body(
      columns = vars(sd),
      rows = sd > 0.4)) %>% 
  tab_footnote(
    footnote = "ヒオウギアヤメ。アヤメ科アヤメ属に分類される多年草",
    locations = cells_body(
      columns = vars(Species),
      rows = Species == "setosa"))

以上、gtパッケージの基本的な作表関数を紹介しました。

gt パッケージの紹介 ~Rで作表の決定版!?~ (1)

Rで綺麗な表を作るパッケージgtの存在を知りました。神ライブラリの予感がしたので少し調べたり触ったりしてたことをまとめます。
いままではknitr::kable()DT::datatable()を使っていたのですが、本格的に乗り換えを検討しています。

gtパッケージとは

  • Rで綺麗な表を作るライブラリ。
  • DTパッケージとは異なり、インタラクティブな操作はできな。
  • 作図におけるggplot2的ポジションを狙っていると思われる。
  • tidyverseのスタイルガイドに準拠しており、パイプ演算子%>%を用いて、細かい表の調整をブロックのように組み合わせることができる。

gtパッケージで作れる表の形

gtパッケージを使うとどのような表をつくることができるか、公式サイトから図を拝借させていただきました。

gtで作れる表の形

図より、表が以下の要素から構成されていることがわかります。table body以外は必ずしも付ける必要はなく、場合に応じて付け足していくことになります。

  • table body : 表の本体。値が入る部分
  • table header : ヘッダー。タイトルとサブタイトル
  • table footer : フッター。注釈やリファレンスなど
  • column labels : 列名。複数列に対してラベルをつけることもできる
  • stub : 行名。インデックス
  • stub head : 行名の上にくる部分

基本的な流れ

  1. 表にするデータフレームの用意
    • data.frame, tibble, data.tableのいずれでも良い。
  2. gt()によるgt_tblオブジェクト作成
  3. 細々した調整
  4. 出力。保存など。
    • なんとhtml形式だけでなく、latex形式でも作れる!!

gtテーブルオブジェクトの作成:gt()

データフレームを用意し、gt()に渡すことで行います。

# CRANに登録されているのでインストールは install.packages("gt")
library(tidyverse)
library(gt)

df <- iris %>% 
  group_by(Species) %>% 
  summarise(count = n(),
            mean_SepalLength = mean(Sepal.Length),
            sd_SepalLength = sd(Sepal.Length))

tbl_1 <- gt(df)
print(tbl_1)

すると、以下のような表が作成されます。この時点でも十分綺麗ですね。

Species count mean_SepalLength sd_SepalLength
setosa 50 5.006 0.3524897
versicolor 50 5.936 0.5161711
virginica 50 6.588 0.6358796

どんどんリッチにすることができます。たとえばtab_header() を使ってタイトルを付け加えてみます。まるでggplotのように、表のオプションをパイプでつなげていくことができます。

tbl_2 <- tbl_1 %>% 
  tab_header(title = "Edgar Anderson's Iris Data",
             subtitle = "The species are Iris setosa, versicolor, and virginica")
tbl_2
Edgar Anderson's Iris Data
The species are Iris setosa, versicolor, and virginica
Species count mean_SepalLength sd_SepalLength
setosa 50 5.006 0.3524897
versicolor 50 5.936 0.5161711
virginica 50 6.588 0.6358796

様々なgtの関数や使い方はまた次の記事で紹介しようと思います。

表の出力

ggplotと同様、Rmd中やConsole上であればgt_tblオブジェクトをそのままprint()することで表示することができますが、表のhtmlファイルを別で保存するには、gtsave()関数を使います。次のコードでは上で作った表をiris_summary.htmlという名前で保存しています。

gtsave(tbl_2, "iris_summary.html")

なんと、gtsave()の中のファイル名で、拡張子を.texとすると、LaTeX形式で保存することもできます。これで、面倒だったmulticolumnやmultirowなどに悩まされることもなくなるでしょう!!すごい!!

ネットワーククラスタリングについて (1)

大学院での研究では、一部ネットワークにまつわるものをやっていました。ネットワークといっても通信の方ではなく、ノードとエッジから構成されるグラフの方です。 最近は、ネットワークの構造に基づいてノードを教師なしで分類していくネットワーククラスタリングに興味があり、備忘録がてらまとめていきます。また、ここでは簡単のため重複エッジや自己ループを許さない無向グラフのみを対象とします。

0. コミュニティとは

ネットワーク科学では、ノードのクラスタのことをしばしば「コミュニティ」とよびます。人間や企業などの主体をノードとして扱うことが多いからかもしれません。コミュニティの定義は難しそうですが、感覚的な特徴には以下のようなものが考えられます。

  • コミュニティ内では繋がりが密である
  • 大きなネットワークの一部分である
  • コミュニティ外のノードとよりも、コミュニティ内との繋がりが強い

このような感覚的な表現を出発として、コミュニティを表すような様々な概念が定義されてきました。

1. クリーク

「大きなネットワークの一部分では、その全てのノード同士が結びついている」
このような状況は、コミュニティとみなすのに易いでしょう。このような部分グラフを、クリークといいます。クリークを以下で定義します。ここで「極大である」とは、クリーク内のすべてのノードと接続しているノードがクリーク外に存在しないことを意味します。

クリーク:極大である完全誘導部分グラフ

ネットワークにおいて三角形はよく見られますが、大規模なクリークを発見することは難しいでしょう。ノード数が増えたときは「完全部分グラフ」であることが難しくなるため、様々なクリークの条件を緩和することが考えられてきました。

2. クリークの条件緩和

クリークよりも弱いものを紹介します。

  • n-クラン:含まれる任意のノードどうしの距離がn以下であるような極大誘導部分グラフ。直径がn以下となります
  • n-クラブn-クランのうち、直径がnであるもの
  • k-プレックス:含まれるどの頂点の次数もn-k以上である極大誘導部分グラフ
  • k-コア:どの頂点の次数もkを下回らない誘導部分グラフ。k-プレックスのkがクリークとの差を表すのに対し、k-コアのkは絶対的な次数です

また、ネットワークのノード数や密度は様々であるため、コミュニティ内とコミュニティ外の相対的な割合をみる強いコミュニティ弱いコミュニティが知られています。

準備として、N個ノードで構成されるネットワークGの部分グラフのノード集合をSとする。また、Gの隣接行列をAとします。 Aの要素a _{uv}は、ノードu,vが接続されているとき1、接続されていないとき0です。 ここで、ノードuが部分グラフSに対して持つ内部次数と外部次数を定義します。 u自体が部分グラフに属しているかどうかは関係ないことに注意が必要です。

  • 内部次数:k _ u ^ {int} = \sum _ {v \in S} a _{u, v}
  • 外部次数:k _ u ^ {ext} = \sum _ {v \notin S} a _{u, v}

内部次数と外部次数を用いて弱いコミュニティ、強いコミュニティは次のように定義されます。

  • 強いコミュニティ:コミュニティ内の任意のノードu \in Sk _ u ^ {int} > k _ u ^ {ext}
  • 弱いコミュニティ \sum _ {u \in S} k _ u ^ {int} >  \sum _ {u \in S}  k _ u ^ {ext}

3. 凝集性 (cohesion)

強いコミュニティ・弱いコミュニティは「コミュニティとみなせるか否か」を与える定義ですが、「コミュニティになっている程度」を連続値として与える凝集性という指標がしられています。ここで、n _ sは部分グラフ内のノード数とします。

  • 凝集性 \frac{\sum _ {u \in S} k _ u ^ {int}} {n _ s(n _ s-1)} / \frac{\sum _ {u \in S} k _ u ^ {ext}} {n _ s(N-n _ s)}

凝集性は(部分グラフ内での密度) / (部分グラフ内から部分グラフ外に対する密度)で表されているため、「凝集性が1以上であれば、また大きければ大きいほど、部分グラフは外部と区別でき、コミュニティの傾向をもっている」と解釈することができます。

4. モジュラリティ

以上では、1つのコミュニティのあり方について、様々な定義や程度の指標を見てきました。実際のネットワーククラスタリングでは、ネットワーク全体を複数のクラスタに分けることを行います。このような問題はグラフ分割とよばれることがあり、特にモジュール数が自動的に決定されるようなタスクをコミュニティ検出といったりします。妥当なクラスタリングを行うためには「分割の質の良さ」を測る必要がありますが、特に有名な指標としてモジュラリティ (modurality)が知られています。

モジュラリティの根底にあるアイデアは、「ランダムグラフはコミュニティ構造をもたない」というものです。コミュニティの特徴をもう一度振り返ると、「部分グラフ内に張られるリンクの割合がそれ以外よりも多い」ことが重要でした。つまり、与えられた分割に対して、「グループ内で張られているエッジの割合」と「エッジがランダムに張られた場合の期待値」との差が重要になります。

いま、ネットワークGm個の部分グラフ S _ 1, S _ 2, \dots, S _ mに分割し、部分グラフ間に張られるエッジ数の割合を要素にもつm\times mの行列 Eを用意します。つまり、 Ei, j要素はe _ {i, j} =\frac{1}{2\sum _ {u,v} a _ {u,v}} \sum _ {u \in S _ i} \sum _ {v \in S _ j} a _ {u, v}となります。  Eの対角成分は分割されたグループ内で張られるエッジの割合であり、非対角成分は異なるグループ間で張られるエッジの割合です。 また、グループ  i に接続するエッジの割合を考えると、 Eの行和E _ i =  \sum _ {j = 1} ^ m e _ {i, j}となります。

もしネットワークが完全にランダムであり、コミュニティ構造を持たないなら、e _ {i,j}i, jで独立になるため、それぞれの行和の積 {\hat e _ {i,j}} = E _ i E _ jと期待されます。 よって、「グループ内で張られているエッジの割合」と「エッジがランダムに張られた場合の期待値」との差を表すモジュラリティ指標Qは次式で定義することができます。

  • モジュラリティ Q = \sum _ i (e _ {ii} - E _ i ^ 2)

大規模なネットワークではモジュラリティ Qを最大化する厳密解を得るのは困難ですが、近似解を得るような様々なアルゴリズムが存在します。