2つの順序変数間の関係のグラフ


46

2つの順序変数間の関係を示す適切なグラフは何ですか?

私が考えることができるいくつかのオプション:

  1. ランダムジッタを追加した散布図で、ポイントが互いに隠れないようにします。どうやら標準グラフィック-Minitabではこれを「個別値プロット」と呼んでいます。私の意見では、データがインターバルスケールからのものであるかのように、順序レベル間の一種の線形補間を視覚的に促進するため、誤解を招く可能性があります。
  2. 散布図は、サンプリング単位ごとに1つのポイントを描画するのではなく、ポイントのサイズ(面積)がそのレベルの組み合わせの頻度を表すように適合されています。実際にそのようなプロットを見たことがあります。読みづらい場合もありますが、ポイントは規則的に間隔を空けた格子上にあり、データを視覚的に「間引く」というジッター散布図の批判をある程度克服します。
  3. 特に、変数の1つが従属変数として扱われる場合、独立変数のレベルでグループ化されたボックスプロット。従属変数のレベルの数が十分に高くない場合はひどいように見える可能性があります(ウィスカが欠けているか、さらに中央値の視覚的な識別が不可能なさらに悪化した四分位で非常に「フラット」)が、少なくとも中央値と四分位数に注意を引きます順序変数の関連する記述統計。
  4. 頻度を示すヒートマップを含むセルの値の表または空白のグリッド。視覚的には異なりますが、散布図と概念的には類似しており、ポイントエリアに周波数が表示されます。

他のアイデア、またはどのプロットが望ましいかについての考えはありますか?特定の序数対序数プロットが標準とみなされる研究分野はありますか?(私は、周波数ヒートマップがゲノミクスで広まっていることを思い出すようですが、名目対名義の方が多いと思われます。)良い標準参照の提案も大歓迎です。Agrestiから何かを推測しています。

プロットで説明したい場合は、偽のサンプルデータのRコードが続きます。

「運動はあなたにとってどれほど重要ですか?」1 =まったく重要ではない、2 =やや重要でない、3 =重要でも重要でもない、4 =やや重要、5 =非常に重要。

「10分以上のランニングをどのくらい定期的に受けますか?」1 =しない、2 = 2週間に1回未満、3 = 1週間または2週間に1回、4 =週に2回または3回、5 =週に4回以上。

「頻繁に」を従属変数として扱い、「重要性」を独立変数として扱うことが自然な場合、プロットが2つを区別する場合。

importance <- rep(1:5, times = c(30, 42, 75, 93, 60))
often <- c(rep(1:5, times = c(15, 07, 04, 03, 01)), #n=30, importance 1
           rep(1:5, times = c(10, 14, 12, 03, 03)), #n=42, importance 2
           rep(1:5, times = c(12, 23, 20, 13, 07)), #n=75, importance 3
           rep(1:5, times = c(16, 14, 20, 30, 13)), #n=93, importance 4
           rep(1:5, times = c(12, 06, 11, 17, 14))) #n=60, importance 5
running.df <- data.frame(importance, often)
cor.test(often, importance, method = "kendall") #positive concordance
plot(running.df) #currently useless

連続変数に関する関連する質問は、おそらく有用な出発点かもしれません。2つの数値変数間の関係を調べるときの散布図の代替手段は何ですか?


1
スピンプロットはどうですか?
Dimitriy V. Masterov

複数のグループにわたって単変量順序データを表示するための関連する質問も関連する場合があります。順序データの表示-平均、中央値、および平均ランク
-Silverfish

回答:


15

スピンプロット(モザイクプロット)は、ここのサンプルデータではうまく機能しますが、カテゴリの組み合わせがまれであるか存在しない場合、読み取りや解釈が困難になる場合があります。当然、低周波数は小さなタイルで表され、タイルがまったくないことでゼロになることは合理的であり、予想されますが、心理的な難しさは残る可能性があります。また、スピネプロットが好きな人が論文やプレゼンテーションに適した例を選択することも当然ですが、私は公共の場で使用するには面倒すぎる例をしばしば作成しました。逆に、スピネプロットは使用可能なスペースをうまく使用します。

一部の実装では、ユーザーが各タイルを調べて詳細を知ることができるように、インタラクティブなグラフィックスを前提としています。

非常にうまく機能する代替手段は、双方向の棒グラフです(他の多くの名前が存在します)。

例えば参照tabplothttp://www.surveydesign.com.au/tipsusergraphs.html

これらのデータについて、1つの可能なプロット(tabplotStata を使用して作成されますが、まともなソフトウェアでは簡単なはずです)

ここに画像の説明を入力してください

この形式は、個々のバーを行と列の識別子に簡単に関連付けることができ、頻度、比率、またはパーセントで注釈を付けることができることを意味します(結果が自然に忙しすぎると思う場合はそうしないでください)。

いくつかの可能性:

  1. ある変数が別の変数への応答を予測変数と考えることができる場合、通常のように縦軸にプロットすることを考える価値があります。ここで、私は「重要性」を態度を測定するものと考え、問題はそれが行動に影響するかどうか(「しばしば」)です。原因の問題は、これらの架空のデータであってもより複雑になることがよくありますが、ポイントは残ります。

  2. 提案#1は、逆の方がうまく機能している場合、つまり、考えやすく、解釈しやすい場合は常に切り捨てられます。

  3. 多くの場合、パーセントまたは確率の内訳が意味をなします。生の周波数のプロットも有用です。(当然、このプロットには、両方の種類の情報を一度に表示するモザイクプロットの長所がありません。)

  4. もちろん、グループ化された棒グラフまたは積み上げ棒グラフ(またはWSクリーブランドの意味でまだ一般的ではないグループ化されたドットグラフ)の(はるかに一般的な)代替案を試すことができます。この場合、私は彼らが同様に働くとは思わないが、時々彼らはよりよく働く。

  5. 一部のユーザーは、異なる応答カテゴリを異なる色にしたい場合があります。私は異論はありません。あなたが望むなら、あなたは異議を真剣に受け取らないでしょう。

グラフと表をハイブリッド化する戦略は、より一般的に役立つ場合があります。しばしば繰り返される議論は、図と表の分離は印刷の発明とそれが生み出した分業の単なる副作用であったということです。原稿作成者が好きな場所に正確にイラストを掲載するのと同じように、それはもう不要です。


グラフィックを追加していただきありがとうございます。これにより、グラフィックスとテキストデータがどのように組み合わされるかという問題が発生します-一部の人々はバーの上に数字を置くことを好まないことを知っています(バーが実際よりも高く見えるため、手渡す引用がありませんこれはよく知られている意見だと思います)。
シルバーフィッシュ

一方、数字の位置を固定すると、2つの問題のいずれかが発生するようです:数字がバーに重なってしまい、数字が不明瞭になるか、バーの上の数字を固定すると、下部のバーから「切断」されます特に。これらの問題についての良い議論はどこかにありますか?
シルバーフィッシュ

参照は必要ないと思います。それは一般的な態度です。私は他の変種を見る:(1)ディスプレイが忙しすぎる、乱雑などのディスプレイ固有の提案(2)同じ情報が暗黙的であるために数値テキストが冗長であるという概念へのアピール)グラフでは、(3)「男の子は青を、女の子はピンクを着る」という態度は、数字は数字であり、表は表であり、トウェインは会わなければならないという態度です。(3)純粋な偏見として私を打つ。(2)原則として正しいが、それでも数値は役立つことがある;(1)例ごとに考えなければならない。
ニックコックス

特定のトレードオフについての議論は知りません。多くの場合、バーを色付けせずに番号を入れておくとよいでしょう。時にはバーが小さすぎて、これを常に実行できないことがあります。
ニックコックス

30

ヒートマップの簡単な試みを次に示します。黒のセルの境界線を使用してセルを分割しましたが、Glen_bの答えのようにタイルをさらに分離する必要があるかもしれません。

ヒートマップ

library(ggplot2)
runningcounts.df <- as.data.frame(table(importance, often))
ggplot(runningcounts.df, aes(importance, often)) +
   geom_tile(aes(fill = Freq), colour = "black") +
   scale_fill_gradient(low = "white", high = "steelblue")

Andy Wによる以前のコメントに基づく変動プロットは次のとおりです。彼が説明しているように、「これらは基本的にカテゴリデータのビン化された散布図であり、ポイントのサイズはそのビン内の観測数にマッピングされます」参照については

ウィッカム、ハドリー、ヘイケホフマン。2011. 製品プロット可視化とコンピュータグラフィックス(PROC。Infovis `11)上のIEEEトランザクション印刷前のPDF

変動プロット

theme_nogrid <- function (base_size = 12, base_family = "") {
  theme_bw(base_size = base_size, base_family = base_family) %+replace% 
    theme(panel.grid = element_blank())   
}

ggplot(runningcounts.df, aes(importance, often)) +
  geom_point(aes(size = Freq, color = Freq, stat = "identity", position = "identity"), shape = 15) +
  scale_size_continuous(range = c(3,15)) + 
  scale_color_gradient(low = "white", high = "black") +
  theme_nogrid()

1
おそらく、Glen_bの答えのようにタイルをもっと分離する必要があります」-この場合、必要かどうかはわかりません。ここでカテゴリを連続と見なす誘惑ははるかに少ないです。
Glen_b

18

データのスピンプロットがどのように見えるかの例を次に示します。これをStataでかなり迅速に行いましたが、Rの実装があります。私はRでそれがちょうどあるべきだと思います:

spineplot(factor(often)~factor(importance))

Rのカテゴリ変数を指定した場合、スピンプロットは実際にデフォルトのようです:

plot(factor(often)~factor(importance))

多くの場合、カテゴリの部分的な内訳は、重要度のカテゴリごとに表示されます。積み上げバーは、重要度カテゴリが頻繁に与えられる割合を示す垂直寸法で描画されます。水平方向のディメンションは、各重要度カテゴリの割合を示します。したがって、形成されるタイルの領域は、重要度の交差組み合わせごとの頻度、またはより一般的には合計を表します。

ここに画像の説明を入力してください


1
周りを変えました。
Dimitriy V. Masterov

1
ニック・コックス(Stataのスピネプロットの著者)の引用:2つの変数に対する制限は、実際よりも明白です。複合変数は、2つ以上のカテゴリ変数を相互結合することで作成できます。...通常、応答変数はy軸に表示する方が適切です。1つの変数がバイナリの場合、多くの場合、y軸にプロットする方が適切です。当然、これらの提案の間には緊張があります。
Dimitriy V. Masterov

3
上記に同意します。しかし、Stataのデフォルトの色[u] rスキームは、順序変数についてはかなりお粗末です。いくつかの優れた選択肢は、赤や青の異なる色合い、または単にgr {a | e} yscaleの選択肢です。
ニックコックス

3
@Dimitriy同じ状況で任意の色の組み合わせを使用するのは非常に奇妙です!私は、正確な色によって、または正確な色から何かを暗示したり推測したりしませんが、定量化されています。ただし、重要なのは、段階的なスケールが段階的な色のシーケンスとよく一致していることだけです。ヒートマップの色付けにも、そして実際には多くの種類の主題図作成にも、some意性があります。
ニックコックス

2
色が明確である限り、段階的な配色で問題は発生しません。なぜ誰かが補間したくなるのでしょうか?任意の色の論理が見えません。レインボーシーケンスは物理学では理にかなっていますが、人々が色をどのように知覚するかという点では意味がありません(たとえば、黄色と赤があまりにも異なる)。選択肢を通して多くの学生と話すという点で私は証拠を持っています、そして、虹またはフルーツサラダの上に微妙な段階的なシーケンスを見たとき、私は80%が心から「はるかに良い」と言います。青から淡い青を経て淡い赤から赤までがうまく機能します。これを男性だけでなく女性でも試してみてください。
ニックコックス

13

私がこれをやった方法はちょっとしたファッジですが、簡単に修正できます。

これは、ジッタリングアプローチの修正バージョンです。

軸を削除すると、スケールを連続として解釈する誘惑が減ります。ジッターされた組み合わせの周りにボックスを描くと、「スケールブレーク」のようなものがあることを強調します。間隔は必ずしも等しいとは限りません

理想的には、1..5ラベルをカテゴリ名に置き換える必要がありますが、ここでは想像のために残しておきます。それがその意味を伝えていると思います。

 plot(jitter(often)~jitter(importance),data=running.df,bty="n",
    ylim=c(0.5,5.5),xlim=c(0.5,5.5),cex=0.5,pty="s",xaxt="n",yaxt="n") 
 axis(1,tick=TRUE,col=0)
 axis(2,tick=TRUE,col=0)
 rect(rep(seq(0.75,4.75,1),5),rep(seq(0.75,4.75,1),each=5),
       rep(seq(1.25,5.25,1),5),rep(seq(1.25,5.25,1),each=5),
       border=8)

ジッタ付き序数プロット


可能な改良:

i)ブレークを小さくする(個人的にはこれよりも大きいブレークを好む)

ii)擬似ランダムシーケンスを使用して、ボックス内の見かけのパターンの発生率を減らすことを試みます。私の試みはいくらか助けましたが、ポイント数の少ないセルには、多少相関のある外観のサブシーケンスがまだあることがわかります(たとえば、一番上の行の2列目のボックス)。それを回避するために、サブボックスに対して準ランダムシーケンスを初期化する必要があります。(代替手段はラテンハイパーキューブサンプリングである可能性があります。)これを整理すると、ジッタとまったく同じように機能する関数に挿入できます。

準ランダムジッターと大きなボックス

library("fOptions")

 hjit <- runif.halton(dim(running.df)[1],2) 
 xjit <- (hjit[,1]-.5)*0.8
 yjit <- (hjit[,2]-.5)*0.8  

 plot(I(often+yjit)~I(importance+xjit),data=running.df,bty="n",
    ylim=c(0.5,5.5),xlim=c(0.5,5.5),cex=0.5,pty="s",xaxt="n",yaxt="n") 
 axis(1,tick=TRUE,col=0)
 axis(2,tick=TRUE,col=0)
 rect(rep(seq(0.55,4.55,1),5),rep(seq(0.55,4.55,1),each=5),
       rep(seq(1.45,5.45,1),5),rep(seq(1.45,5.45,1),each=5),
       border=8)

1
私はこれが好きです、私にとって、分離はデータの順序的な性質を本当に強調しています!残念なことに、人間の目は、例えばパネル(4,5)および(5,3)の「上向きの傾向」など、ジッターの明らかなパターンに自然に描かれています。プラス面では、「ポイントのカウント」は、ドットサイズで頻度を判断するよりもはるかに自然に感じます。「ジッタの傾向」を乱すことを避けるために、ポイントが均等に配置されている、または中心で規則的なパターンにまとまっているバリアントがありますか?
シルバーフィッシュ

1
@Silverfish、地理学の同様の概念は、ドット密度マップです。地理学者は、規則的なパターンまたは一定量の空白を埋める(ランダムではなく、より間隔が空いている)パターンが、観測者間でより正確な知覚を生み出す傾向があるといういくつかの証拠を発見しました。
アンディW

IMOこれは素晴らしいアイデアですが、この例ではパネル間の間隔が非常に大きいため、傾向を視覚化することは非常に困難です。治療法は病気よりも悪いです(しかし、パネルをもっと近づけることはかなり簡単なはずです)。
アンディW

1
@silverfish 準ランダムジッターは、それに対する可能な解決策です。あなたの懸念は私が自分自身を持っていたものです。
Glen_b

1
非常に素晴らしい!IMOこれは、このインスタンスのスピンプロットよりも優れたオプションです(スパインまたはモザイクプロットは、カテゴリペアの条件付き分布を評価するのに適しています-このジッタードットプロットは、傾向を評価するのが簡単です-データの順序の性質を利用して、単調な関係のタイプ)。
アンディW

7

Rパッケージriverplotの使用:

  data$importance <- factor(data$importance, 
                            labels = c("not at all important",
                                       "somewhat unimportant",
                                       "neither important nor unimportant",
                                       "somewhat important",
                                       "very important"))
  data$often <- factor(data$often, 
                       labels = c("never",
                                  "less than once per fortnight",
                                  "once every one or two weeks",
                                  "two or three times per week",
                                  "four or more times per week"))

  makeRivPlot <- function(data, var1, var2, ...) {

    require(plyr)
    require(riverplot)
    require(RColorBrewer)

    names1 <- levels(data[, var1])
    names2 <- levels(data[, var2])

    var1 <- as.numeric(data[, var1])
    var2 <- as.numeric(data[, var2])

    edges <- data.frame(var1, var2 + max(var1, na.rm = T))
    edges <- count(edges)

    colnames(edges) <- c("N1", "N2", "Value")

    nodes <- data.frame(ID     = c(1:(max(var1, na.rm = T) +
                                      max(var2, na.rm = T))),
                        x      = c(rep(1, times = max(var1, na.rm = T)),
                                   rep(2, times = max(var2, na.rm = T))),
                        labels = c(names1, names2) ,
                        col    = c(brewer.pal(max(var1, na.rm = T), "Set1"),
                                   brewer.pal(max(var2, na.rm = T), "Set1")),
                        stringsAsFactors = FALSE)

    nodes$col <- paste(nodes$col, 95, sep = "")

    return(makeRiver(nodes, edges))

  }

a <- makeRivPlot(data, "importance", "often")

riverplot(a, srt = 45)

ここに画像の説明を入力してください


1
(+1)これに平行座標を使用するというアイデアが好きです!左から右に色が流れると、ダイアグラムを通るパスをトレースし、「頻繁に」回答がどのように分解されるかを確認する方が簡単だと思います(従属変数として「頻繁に」表示され、説明変数として重要性」)。そのようなプロットのいくつかのインタラクティブな実装では、軸をクリックしてその変数で色を付けることができます。これは便利です。
シルバーフィッシュ

1
比較のために、カテゴリデータ用に設計されたRobert Kosaraの「パラレルセット」視覚化では、色が図を流れます。
シルバーフィッシュ

6

私が元々考えなかった別の考えはふるいプロットでした。

ここに画像の説明を入力してください

各タイルのサイズは、予想される頻度に比例します。長方形の中の小さな正方形は実際の周波数を表しています。したがって、正方形の密度が高いほど、予想される頻度よりも高いことを示します(青の影付き)。低密度の正方形(赤)は、予想される周波数よりも低いことを意味します。

色が残差のサイズだけでなく、サインを表す場合、私はそれを好むと思います。これは、期待周波数と観測周波数が類似しており、残差がゼロに近いエッジの場合に特に当てはまります。赤と青の二分法は、小さな偏差を強調しすぎるようです。

Rでの実装:

library(vcd)
runningcounts.df <- as.data.frame(table(importance, often))
sieve(Freq ~ often + importance, data=runningcounts.df, shade= TRUE)

1
色がサイズだけでなく記号を表すというあなたの好みに関して、1つの可能性は、予想との差が比較的小さいときに色をより灰色にすることです。
Glen_b

6

Rのファセット付き棒グラフ。「重要度」の各レベルでの「頻繁」の分布を非常に明確に示します。しかし、最大数が「重要度」のレベル間でさらに異なっていた場合、それほどうまく機能しなかったでしょう。多くの空きスペースを避けるためscales="free_y"にggplot(ここを参照)に設定するのは簡単ですが、バーが非常に小さいため、分布の形状を「重要度」の低周波数レベルで識別するのは困難です。おそらくこれらの状況では、代わりに垂直軸の相対頻度(条件付き確率)を使用する方が適切です。

多面的な棒グラフ

Nick CoxがリンクしたStataのタブプロットほど「きれい」ではありませんが、同様の情報を伝えます。

Rコード:

library(ggplot)
running2.df <- data.frame(often = factor(often, labels = c("never", "less than once per fortnight", "once every one or two weeks", "two or three times per week", "four or more times per week")), importance = factor(importance, labels = c("not at all important", "somewhat unimportant", "neither important nor unimportant", "somewhat important", "very important")))
ggplot(running2.df, aes(often)) + geom_bar() +
  facet_wrap(~ importance, ncol = 1) +
  theme(axis.text.x=element_text(angle = -45, hjust = 0)) +
  theme(axis.title.x = element_blank())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.