Wykres zależności między dwiema zmiennymi porządkowymi

46

Jaki jest odpowiedni wykres ilustrujący związek między dwiema zmiennymi porządkowymi?

Kilka opcji, o których mogę myśleć:

  1. Wykres rozproszenia z dodanym drganiami losowymi, aby zatrzymać ukrywanie się punktów. Niby standardowa grafika - Minitab nazywa to „wykresem wartości indywidualnych”. Moim zdaniem może to być mylące, ponieważ wizualnie zachęca do pewnego rodzaju interpolacji liniowej między poziomami porządkowymi, tak jakby dane pochodziły ze skali interwałowej.
  2. Wykres rozproszenia dostosowany w taki sposób, że rozmiar (obszar) punktu reprezentuje częstotliwość tej kombinacji poziomów, zamiast rysować jeden punkt dla każdej jednostki próbkowania. Od czasu do czasu widziałem takie wątki w praktyce. Mogą być trudne do odczytania, ale punkty leżą na regularnie rozmieszczonej sieci, która nieco przezwycięża krytykę roztrzęsionego wykresu rozrzutu, że wizualnie „interweniuje” dane.
  3. W szczególności, jeśli jedną ze zmiennych traktuje się jako zależną, wykres ramkowy pogrupowany według poziomów zmiennej niezależnej. Prawdopodobnie wygląda okropnie, jeśli liczba poziomów zmiennej zależnej nie jest wystarczająco wysoka (bardzo „płaska” z brakującymi wąsami lub jeszcze gorszymi zapadniętymi kwartylami, co uniemożliwia wizualną identyfikację mediany), ale przynajmniej zwraca uwagę na medianę i kwartyle, które są odpowiednie statystyki opisowe dla zmiennej porządkowej.
  4. Tabela wartości lub pusta siatka komórek z mapą cieplną wskazującą częstotliwość. Wizualnie inny, ale koncepcyjnie podobny do wykresu punktowego z obszarem punktowym pokazującym częstotliwość.

Czy są inne pomysły lub przemyślenia, które wątki są lepsze? Czy są jakieś dziedziny badań, w których pewne wykresy porządkowe kontra porządkowe są uważane za standardowe? (Wydaje mi się, że przypominam mapę termiczną częstotliwości, która jest szeroko rozpowszechniona w genomice, ale podejrzewam, że częściej dotyczy ona wartości nominalnej vs. nominalnej.) Sugestie dotyczące dobrego standardowego odniesienia również byłyby bardzo mile widziane, zgaduję coś z Agresti.

Jeśli ktoś chce zilustrować za pomocą wykresu, następuje kod R dla fałszywych danych przykładowych.

„Jak ważne jest dla ciebie ćwiczenie?” 1 = wcale nie ważne, 2 = nieco nieważne, 3 = ani ważne, ani nieważne, 4 = dość ważne, 5 = bardzo ważne.

„Jak regularnie bierzesz 10 minut lub dłużej?” 1 = nigdy, 2 = rzadziej niż raz na dwa tygodnie, 3 = raz na jeden lub dwa tygodnie, 4 = dwa lub trzy razy w tygodniu, 5 = cztery lub więcej razy w tygodniu.

Jeśli byłoby naturalne traktować „często” jako zmienną zależną, a „ważność” jako zmienną niezależną, jeśli wykres rozróżnia między nimi.

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

Powiązane pytanie dotyczące zmiennych ciągłych było dla mnie pomocne, a może przydatny punkt wyjścia: jakie są alternatywy dla wykresów rozrzutu podczas badania związku między dwiema zmiennymi numerycznymi?

Srebrna Rybka
źródło
1
Co powiesz o spineplot?
Dimitriy V. Masterov
Powiązane pytanie dotyczące wyświetlania jednowymiarowych danych porządkowych w kilku grupach może być również istotne: Wyświetlanie danych porządkowych - środki, mediany i średnie stopnie
Silverfish

Odpowiedzi:

15

Wykres kręgosłupa (wykres mozaiki) działa dobrze dla przykładowych danych tutaj, ale może być trudny do odczytania lub interpretacji, jeśli niektóre kombinacje kategorii są rzadkie lub nie istnieją. Oczywiście rozsądne i oczekiwane jest, że niska częstotliwość jest reprezentowana przez małą płytkę, a zero przez żadną płytkę, ale trudności psychologiczne mogą pozostać. To również naturalne, że ludzie lubiący kręgosłupy wybierają przykłady, które dobrze sprawdzają się w ich artykułach lub prezentacjach, ale często tworzyłem przykłady, które były zbyt niechlujne, aby można je było wykorzystywać publicznie. I odwrotnie, wykres kręgosłupa dobrze wykorzystuje dostępną przestrzeń.

Niektóre implementacje zakładają interaktywną grafikę, aby użytkownik mógł przesłuchać każdy kafelek, aby dowiedzieć się więcej na ten temat.

Alternatywą, która może również działać całkiem dobrze, jest dwukierunkowy wykres słupkowy (istnieje wiele innych nazw).

Zobacz na przykład tabplotw http://www.surveydesign.com.au/tipsusergraphs.html

Dla tych danych jest jeden możliwy wykres (stworzony przy użyciu tabplotStata, ale powinien być łatwy w każdym przyzwoitym oprogramowaniu)

wprowadź opis zdjęcia tutaj

Format oznacza, że ​​łatwo jest powiązać poszczególne słupki z identyfikatorami wierszy i kolumn oraz że można dodawać adnotacje z częstotliwościami, proporcjami lub procentami (nie rób tego, jeśli uważasz, że wynik jest zbyt zajęty, naturalnie).

Niektóre możliwości:

  1. Jeśli jedną zmienną można uznać za odpowiedź na drugą jako predyktor, warto pomyśleć o narysowaniu jej jak zwykle na osi pionowej. Tutaj myślę o „znaczeniu” jako pomiarze postawy, a następnie pytaniem jest, czy wpływa ono na zachowanie („często”). Problem przyczynowy jest często bardziej skomplikowany nawet w przypadku tych wyimaginowanych danych, ale sedno pozostaje.

  2. Sugestia nr 1 jest zawsze ważniejsza, jeśli odwrotność działa lepiej, co oznacza, że ​​łatwiej jest myśleć i interpretować.

  3. Podziały procentowe lub prawdopodobieństwa często mają sens. Przydatny może być również wykres pierwotnych częstotliwości. (Oczywiście, fabuła ta nie ma zalet mozaikowych wykresów pokazujących oba rodzaje informacji naraz.)

  4. Możesz oczywiście wypróbować (znacznie bardziej powszechne) alternatywy zgrupowanych wykresów słupkowych lub skumulowanych wykresów słupkowych (lub wciąż dość nietypowych zgrupowanych wykresów punktowych w sensie WS Cleveland). W tym przypadku nie sądzę, aby działały tak samo, ale czasami działają lepiej.

  5. Niektórzy mogą chcieć inaczej pokolorować różne kategorie odpowiedzi. Nie mam sprzeciwu, a jeśli chcesz, nie podejmiesz poważnie zastrzeżeń.

Strategia hybrydyzacji wykresu i tabeli może być bardziej użyteczna, a nawet wcale nie taka, jakiej chcesz. Często powtarzanym argumentem jest to, że rozdzielenie rysunków i tabel było tylko efektem ubocznym wynalazku druku i podziału pracy, który on wytworzył; jest to znów niepotrzebne, podobnie jak pisanie manuskryptów umieszczających ilustracje dokładnie tak, jak i gdzie lubią.

Nick Cox
źródło
Dziękujemy za dodanie grafiki. Rodzi to pytanie o to, jak grafika i dane tekstowe łączą się - wiem, że niektórzy ludzie nie lubią umieszczać liczb na górze słupków (ponieważ sprawia, że ​​słupki wydają się wyższe niż w rzeczywistości; nie mam za co podawać to, ale myślę, że to dobrze znana opinia).
Silverfish
Z drugiej strony ustalenie pozycji liczb wydaje się stwarzać jeden z dwóch problemów: albo liczby mogą nałożyć się na słupki, co je zasłania, albo ustalenie liczb nad słupkami może „odłączyć” je od dolnych słupków w szczególności. Czy gdzieś jest dobra dyskusja na te tematy?
Silverfish,
Nie sądzę, że potrzebujesz referencji; to wspólne podejście. Widzę inne warianty: (1) specyficzne dla wyświetlacza sugestie, że wyświetlacz jest po prostu zbyt zajęty, nieporządny itp. (2) odwołanie do twierdzenia, że ​​tekst numeryczny jest zbędny, ponieważ ta sama informacja jest niejawna (lub według niektórych wyraźnych ) na wykresie w jakikolwiek sposób (3) postawa „chłopcy noszą niebieskie, a dziewczęta różowe”, że liczby to liczby, a tabele to tabele, a twarze się nie spotkają. (3) wydaje mi się czystym uprzedzeniem; (2) jest w zasadzie poprawny, ale mimo to liczby mogą pomóc; (1) należy przemyśleć przykład po przykładzie.
Nick Cox,
Nie znam dyskusji na temat konkretnych kompromisów. Pozostawienie słupków bezbarwnych, aby można było w nich wstawić liczby, jest często dobrym pomysłem. Czasami paski mogą być zbyt małe, aby można było to zawsze robić.
Nick Cox,
30

Oto szybka próba mapy cieplnej , użyłem czarnych granic komórek do rozbicia komórek, ale być może płytki powinny być oddzielone bardziej niż w odpowiedzi Glen_b.

Mapa ciepła

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")

Oto wykres fluktuacji oparty na wcześniejszym komentarzu Andy'ego W. Jak on je opisuje „są to w zasadzie tylko zbiorcze wykresy rozrzutu dla danych kategorycznych, a wielkość punktu jest odwzorowana na liczbę obserwacji, które mieszczą się w tym przedziale”. Dla odniesienia patrz

Wickham, Hadley i Heike Hofmann. 2011. Wykresy produktów . Transakcje IEEE dotyczące wizualizacji i grafiki komputerowej (Proc. Infovis `11) . Wstępnie wydrukuj plik PDF

wykres fluktuacji

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()
Silverfish
źródło
1
być może płytki powinny być oddzielone bardziej niż w odpowiedzi Glen_b ” - nie jestem pewien, czy w tym przypadku jest to konieczne, istnieje znacznie mniej pokusy, aby kategorie były tutaj ciągłe.
Glen_b
18

Oto przykład, jak wyglądałby wykres kręgosłupa danych. Zrobiłem to w Stata dość szybko, ale nie realizacja R . Myślę, że w R powinno być tylko:

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

Wykres kręgosłupa wydaje się być domyślny, jeśli podasz R zmienne kategorialne:

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

Podział ułamkowy kategorii często jest pokazany dla każdej kategorii ważności. Ułożone pręty są rysowane w wymiarze pionowym pokazującym ułamek często danej kategorii ważności. Wymiar poziomy pokazuje ułamek w każdej kategorii ważności. Zatem obszary uformowanych płytek reprezentują częstotliwości, lub bardziej ogólnie sumy, dla każdej kombinacji znaczenia i często.

wprowadź opis zdjęcia tutaj

Dimitriy V. Masterov
źródło
1
Zmieniłem to wokół.
Dimitriy V. Masterov
1
Cytując Nicka Coxa (autora wykresu kręgosłupa Staty): Ograniczenie do dwóch zmiennych jest bardziej widoczne niż rzeczywiste. Zmienne złożone mogą być tworzone przez kombinację dwóch lub więcej zmiennych kategorialnych .... Zmienna odpowiedzi jest zwykle lepiej pokazana na osi y. Jeśli jedna zmienna jest binarna, często lepiej jest wykreślić ją na osi y. Oczywiście między tymi sugestiami może być pewne napięcie.
Dimitriy V. Masterov
3
Zgadzam się z powyższym. Ale domyślny schemat colo [u] r Staty jest dość kiepski dla zmiennych porządkowych. Kilka dobrych alternatyw to różne odcienie czerwieni i / lub niebieskiego lub po prostu wybory.
Nick Cox
3
@Dimitriy Uważam, że bardzo dziwne jest stosowanie dowolnej mieszanki kolorów w tej samej sytuacji! Nie sugeruję ani nie wywnioskuję niczego z dokładnych kolorów, nawet ilościowych. Chodzi tylko o to, że stopniowana skala jest dobrze dopasowana do stopniowanej sekwencji kolorów. Kolorystyka map termicznych jest również dowolna, a nawet w wielu rodzajach kartografii tematycznej.
Nick Cox
2
Nie widzę problemu ze stopniowaną kolorystyką, dopóki kolory są wyraźne. Dlaczego ktoś miałby pokusę interpolacji? Nie widzę logiki do dowolnych kolorów. Sekwencje tęczy mają sens w fizyce, ale nie pod względem tego, jak ludzie postrzegają kolory (np. Żółty i czerwony są zbyt różne). Mam dowody na to, że rozmawiam z wieloma studentami poprzez wybory i powiedziałbym, że 80% szczerze mówi „To znacznie lepiej”, gdy widzą subtelną stopniowaną sekwencję nad tęczami lub sałatką owocową. Niebieski przez jasnoniebieski przez jasnoczerwony do czerwonego działa dobrze. Wypróbuj to na kobietach i mężczyznach.
Nick Cox
13

Sposób, w jaki to zrobiłem, to trochę krówka, ale można to łatwo naprawić.

To jest zmodyfikowana wersja jitterowego podejścia.

Usunięcie osi zmniejsza pokusę interpretowania skali jako ciągłej; rysowanie ramek wokół roztrzęsionych kombinacji podkreśla, że ​​istnieje coś takiego jak „podziałka skali” - że interwały niekoniecznie są równe

Idealnie, etykiety 1..5 powinny zostać zastąpione nazwami kategorii, ale na razie pozostawię to wyobraźni; Myślę, że przekazuje sens tego.

 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)

roztrzęsiony wykres porządkowo-porządkowy


Możliwe udoskonalenia:

i) zmniejszanie przerw (osobiście wolę większe przerwy) i

ii) próba zastosowania quasirandomowej sekwencji w celu zmniejszenia częstości występowania widocznego wzoru w ramkach. Chociaż moja próba nieco pomogła, widać, że w komórkach o mniejszej liczbie punktów nadal są podsekwencje o mniej lub bardziej skorelowanym wyglądzie (np. Ramka w górnym rzędzie, druga kolumna). Aby tego uniknąć, może być konieczne zainicjowanie quasi-losowej sekwencji dla każdego podrozdziału. (Alternatywą może być próbkowanie Latin Hypercube). Po rozwiązaniu problemu można go wstawić do funkcji, która działa dokładnie jak jitter.

quasi-losowe jitter i większe pudełka

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)
Glen_b
źródło
1
Podoba mi się to, dla mnie separacja naprawdę podkreśla porządek danych! Niestety ludzkie oko w naturalny sposób przyciąga pozorne wzorce drżenia, np. „Trendy wzrostowe” w panelach (4,5) i (5,3). Z drugiej strony „liczenie punktów” wydaje mi się bardziej naturalne niż ocenianie częstotliwości według wielkości kropki. Czy istnieją warianty, w których punkty są rozmieszczone równomiernie lub zlepione w regularne wzory w centrach, aby uniknąć rozpraszających „trendów jittera”?
Silverfish
1
@Silverfish, podobna koncepcja geograficzna to mapy gęstości kropek. Geografowie znaleźli pewne dowody na to, że regularne wzory lub wzory, które wypełniają pewną ilość białych znaków (tak, że są rozmieszczone dalej niż losowo), mają tendencję do generowania dokładniejszych spostrzeżeń wśród obserwatorów.
Andy W
IMO to świetny pomysł, ale odstępy między panelami są w tym przykładzie tak duże, że bardzo trudno jest wizualizować każdy trend. Lekarstwo jest gorsze niż choroba (ale powinno być dość łatwo zbliżyć panele do siebie).
Andy W
1
@ quasi-losowy jittering @silverfish byłby możliwym rozwiązaniem tego. Twoja sprawa dotyczy mnie samego.
Glen_b
1
Bardzo dobrze! IMO jest w tym przypadku lepszą opcją niż wykres kręgosłupa (wykresy kręgosłupa lub mozaiki lepiej oceniają rozkłady warunkowe dla dowolnej pary kategorii - ten przerywany wykres kropkowy jest łatwiejszy do oceny trendów - wykorzystując porządkowy charakter danych i zakładając, że niektóre rodzaj relacji monotonicznej).
Andy W
7

Korzystanie z pakietu 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)

wprowadź opis zdjęcia tutaj

DL Dahly
źródło
1
(+1) Podoba mi się pomysł użycia równoległych współrzędnych ! Myślę, że łatwiej byłoby prześledzić ścieżki na diagramie i zobaczyć, jak rozkładają się „często” odpowiedzi, jeśli kolory płyną od lewej do prawej (schemat, który skutecznie wyświetlałby „często” jako zmienną zależną i „ znaczenie ”jako zmienna objaśniająca). W niektórych interaktywnych implementacjach takich wykresów można kliknąć oś, aby pokolorować według tej zmiennej, co jest przydatne.
Silverfish,
1
Dla porównania wizualizacja „zbiorów równoległych” Roberta Kosary , zaprojektowana dla danych kategorycznych, ma kolory przepływające przez diagram.
Silverfish,
6

Innym pomysłem, o którym nie myślałem, była fabuła sitowa .

wprowadź opis zdjęcia tutaj

Rozmiar każdej płytki jest proporcjonalny do oczekiwanej częstotliwości; małe kwadraty w prostokątach reprezentują rzeczywiste częstotliwości. Stąd większa gęstość kwadratów wskazuje wyższą niż oczekiwana częstotliwość (i jest zacieniowana na niebiesko); mniejsza gęstość kwadratów (czerwona) dotyczy częstotliwości niższej niż oczekiwana.

Myślę, że wolałbym, aby kolor reprezentował rozmiar, a nie tylko znak pozostałości. Jest to szczególnie prawdziwe w przypadkach krawędziowych, w których częstotliwości oczekiwane i obserwowane są podobne, a reszta jest bliska zeru; dychotomiczny schemat czerwono-niebieski wydaje się przeceniać niewielkie odchylenia.

Wdrożenie w R:

library(vcd)
runningcounts.df <- as.data.frame(table(importance, often))
sieve(Freq ~ often + importance, data=runningcounts.df, shade= TRUE)
Silverfish
źródło
1
Jeśli chodzi o twoją preferencję, że kolor reprezentuje zarówno rozmiar, jak i znak, jedną z możliwości jest uczynienie kolorów bardziej szarymi, gdy różnica od oczekiwanej jest stosunkowo niewielka.
Glen_b
6

Fasetowany wykres słupkowy w R. Bardzo wyraźnie pokazuje rozkład „często” na każdym poziomie „ważności”. Ale nie działałoby to tak dobrze, gdyby maksymalna liczba różniła się bardziej między poziomami „ważności”; dość łatwo jest ustawić scales="free_y"ggplot ( patrz tutaj ), aby uniknąć dużej ilości pustej przestrzeni, ale kształt rozkładu byłby trudny do zauważenia przy poziomach „ważności” niskich częstotliwości, ponieważ słupki byłyby tak małe. Być może w takich sytuacjach lepiej jest zamiast tego zastosować częstotliwość względną (prawdopodobieństwo warunkowe) na osi pionowej.

fasetowany wykres słupkowy

Nie jest tak „czysty” jak tabulator w Stacie, z którym łączył się Nick Cox, ale przekazuje podobne informacje.

Kod 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())
Silverfish
źródło