Hoe te tellen per groep in R

Tellen op basis van meerdere groepen - ook wel kruistabelrapporten genoemd - kan een handige manier zijn om gegevens te bekijken, variërend van opiniepeilingen tot medische tests. Hoe stemden mensen bijvoorbeeld per geslacht en leeftijdsgroep? Hoeveel softwareontwikkelaars die zowel R als Python gebruiken, zijn mannen versus vrouwen?

Er zijn veel manieren om dit soort tellen per categorie in R te doen. Hier wil ik enkele van mijn favorieten delen.

Voor de demo's in dit artikel gebruik ik een subset van de Stack Overflow Developers-enquête, die ontwikkelaars enquêteert over tientallen onderwerpen, variërend van salarissen tot gebruikte technologieën. Ik zal het opsommen met kolommen voor gebruikte talen, geslacht en of ze coderen als een hobby. Ik heb ook mijn eigen LanguageGroup-kolom toegevoegd om aan te geven of een ontwikkelaar heeft gerapporteerd met R, Python, beide of geen van beide.

Als u dit wilt volgen, vindt u op de laatste pagina van dit artikel instructies voor het downloaden en wringen van de gegevens om dezelfde gegevensset te krijgen die ik gebruik.

De gegevens hebben één rij voor elke enquêtereactie en de vier kolommen zijn allemaal tekens.

str (mydata) 'data.frame': 83379 obs. van 4 variabelen: $ Geslacht: chr "Man" "Man" "Man" "Man" ... $ LanguageWorkedWith: chr "HTML / CSS; Java; JavaScript; Python" "C ++; HTML / CSS; Python" "HTML / CSS "" C; C ++; C #; Python; SQL "... $ Hobbyist: chr" Ja "" Nee "" Ja "" Nee "... $ LanguageGroup: chr" Python "" Python "" Noch "" Python "...

Ik heb de onbewerkte gegevens gefilterd om de kruistabellen beter beheersbaar te maken, inclusief het verwijderen van ontbrekende waarden en alleen de twee grootste geslachten, Man en Vrouw, te nemen.

Het conciërge-pakket

Dus, wat is de uitsplitsing naar geslacht binnen elke taalgroep? Voor dit type rapportage in een dataframe is een van mijn go-to-tools de tabyl()functie van het conciërgepakket . 

De basisfunctie tabyl()retourneert een dataframe met tellingen. De eerste kolomnaam die u aan een tabyl()argument toevoegt, wordt de rij en de tweede de kolom

bibliotheek (conciërge) tabyl (mydata, Gender, LanguageGroup)

Geslacht Beide Geen van beide Python R Man 3264 43908 29044969 Vrouw 374 3705 1940175

Het mooie tabyl()is dat het ook heel gemakkelijk is om percentages te genereren. Als u percentages voor elke kolom wilt zien in plaats van onbewerkte totalen, voegt u toe adorn_percentages("col"). U kunt die resultaten vervolgens omzetten in een opmaakfunctie zoals  adorn_pct_formatting().

tabyl (mydata, Gender, LanguageGroup)%>%

adorn_percentages ("col")%>%

adorn_pct_formatting (cijfers = 1)

Geslacht Beide Geen van beide Python R Man 89,7% 92,2% 93,7% 84,7% Vrouw 10,3% 7,8% 6,3% 15,3%

Voeg toe om percentages per rij te zien adorn_percentages("row")

Als je een derde variabele wilt toevoegen, zoals Hobbyist, is dat ook gemakkelijk.

tabyl (mydata, geslacht, taalgroep, hobbyist)%>%

adorn_percentages ("col")%>%

adorn_pct_formatting (cijfers = 1)

Op deze manier wordt het echter een beetje moeilijker om resultaten visueel te vergelijken op meer dan twee niveaus. Deze code retourneert een lijst met één dataframe voor elke keuze op het derde niveau:

$ Nee Geslacht Beide Geen Python R Man 79,6% 86,7% 86,4% 74,6% Vrouw 20,4% 13,3% 13,6% 25,4% $ Ja Geslacht Beide Geen Python R Man 91,6% 93,9% 95,0% 88,0% Vrouw 8,4% 6,1% 5,0% 12,0%

Het CGPfunctions-pakket

Het CGPfunctions-pakket is het bekijken waard voor enkele snelle en gemakkelijke manieren om kruistabelgegevens te visualiseren. Installeer het vanaf CRAN met het gebruikelijke install.packages("CGPfunctions").

Het pakket heeft twee interessante functies voor het onderzoeken van kruistabellen: PlotXTabs()en PlotXTabs2(). Deze code retourneert staafdiagrammen van de gegevens (eerste grafiek hieronder):

bibliotheek (CGPfunctions)

PlotXTabs (mydata)

Schermopname door Sharon Machlis,

PlotXTabs2(mydata) maakt een grafiek met een ander uiterlijk en enkele statistische samenvattingen (tweede grafiek links).

Als je die samenvattingen niet nodig hebt of wilt, kun je ze verwijderen met results.subtitle = FALSE, zoals  PlotXTabs2(mydata, LanguageGroup, Gender, results.subtitle = FALSE).

Schermopname door Sharon Machlis,

PlotXTabs2()heeft een paar dozijn argumentopties, waaronder titel, bijschrift, legendes, kleurenschema en een van de vier plot-typen: zijkant, stapel, mozaïek of percentage. Er zijn ook opties die ggplot2-gebruikers bekend zijn, zoals ggtheme en palette. U kunt meer details zien in het helpbestand van de functie.

Het vtree-pakket

Het vtree-pakket genereert afbeeldingen voor kruistabellen in tegenstelling tot grafieken. De hoofdfunctie vtree()uitvoeren op één variabele, zoals 

bibliotheek (vtree)

vtree (mydata, "LanguageGroup")

krijgt u dit basisantwoord:

Sharon Machlis,

Ik ben niet enthousiast over de standaardkleuren hier, maar je kunt een RColorBrewer-palet inwisselen. vtree's palet argument gebruikt palet nummers , geen namen; u kunt zien hoe ze zijn genummerd in de documentatie van het vtree-pakket. Ik zou bijvoorbeeld 3 voor Groenen en 5 voor Paars kunnen kiezen. Helaas geven die standaardwaarden je een intensere kleur voor lagere telnummers, wat niet altijd logisch is (en in dit voorbeeld niet goed werkt voor mij). Ik kan dat standaardgedrag veranderen sortfill = TRUEdoor de intensere kleur te gebruiken voor de hogere waarde. 

vtree (mydata, "LanguageGroup", palette = 3, sortfill = TRUE)

Sharon Machlis,

Als u merkt dat de donkere kleur het moeilijk maakt om tekst te lezen, zijn er enkele opties. Een optie is om het gewone argument te gebruiken, zoals  vtree(mydata, "LanguageGroup", plain = TRUE). Een andere optie is om een ​​enkele vulkleur in te stellen in plaats van een palet, met behulp van het fillcolorargument, zoals  vtree(mydata, LanguageGroup", fillcolor = "#99d8c9").

Als u twee variabelen in een kruistabelrapport wilt bekijken, voegt u gewoon een tweede kolomnaam en palet of kleur toe als u de standaard niet wilt. U kunt de gewone optie gebruiken of twee paletten of twee kleuren specificeren. Hieronder heb ik specifieke kleuren gekozen in plaats van paletten, en ik heb ook de grafiek gedraaid om verticaal te lezen.

vtree (mydata, c ("LanguageGroup", "Gender"),

fillcolor = c (LanguageGroup = "# e7d4e8", Gender = "# 99d8c9"),

horizont = FALSE)

Sharon Machlis,

You can add more than two categories, although it gets a bit harder to read and follow as the tree grows. If you’re only interested in some of the branches, you can specify which to display with the keep argument. Below, I set vtree() to show only people who use R without Python or who use both R and Python.

vtree(mydata, c("Gender", "LanguageGroup", "Hobbyist"),

horiz = FALSE, fillcolor = c(LanguageGroup = "#e7d4e8",

Gender = "#99d8c9", Hobbyist = "#9ecae1"),

keep = list(LanguageGroup = c("R", "Both")), showcount = FALSE)

Met de boom steeds zo druk, ik denk dat het helpt om ofwel de telling of het percentage als knooppunt labels, niet beide. Dus dat laatste argument in de code hierboven,  showcount = FALSEstelt de grafiek in om alleen percentages weer te geven en niet tellingen.

Sharon Machlis,

Meer tellen door groepsopties

Er zijn andere handige manieren om te groeperen en te tellen in R, inclusief basis R, dplyr en data.table. Base R heeft de  xtabs()functie specifiek voor deze taak. Let op de onderstaande syntaxis van de formule: een tilde en dan een variabele plus een andere variabele.

xtabs (~ LanguageGroup + Gender, data = mydata)

Geslacht Taal Groep Man Vrouw Beide 3264374 Geen van beide 43908 3705 Python 29044 1940 R 969175

De count()functie van dplyr combineert "groeperen op" en "tellen rijen in elke groep" tot een enkele functie.

bibliotheek (dplyr)

my_summary%

count(LanguageGroup, Gender, Hobbyist, sort = TRUE)

my_summary LanguageGroup Gender Hobbyist n 1 Neither Man Yes 34419 2 Python Man Yes 25093 3 Neither Man No 9489 4 Python Man No 3951 5 Both Man Yes 2807 6 Neither Woman Yes 2250 7 Neither Woman No 1455 8 Python Woman Yes 1317 9 R Man Yes 757 10 Python Woman No 623 11 Both Man No 457 12 Both Woman Yes 257 13 R Man No 212 14 Both Woman No 117 15 R Woman Yes 103 16 R Woman No 72

In the three lines of code below, I load the data.table package, create a data.table from my data, and then use the special .N data.table symbol that stands for number of rows in a group. 

library(data.table)

mydt <- setDT(mydata)

mydt[, .N, by = .(LanguageGroup, Gender, Hobbyist)]

Visualizing with ggplot2

Zoals met de meeste gegevens, is ggplot2 een goede keuze om samengevatte resultaten te visualiseren. De eerste ggplot-grafiek hieronder zet LanguageGroup op de X-as en het aantal voor elk op de Y-as. Opvulkleur geeft aan of iemand zegt dat hij codeert als een hobby. En facet_wrap zegt: maak een aparte grafiek voor elke waarde in de kolom Geslacht.

bibliotheek (ggplot2)

ggplot (my_summary, aes (LanguageGroup, n, fill = Hobbyist)) +

geom_bar (stat = "identiteit") +

facet_wrap (facets = vars (geslacht))

Sharon Machlis,

Omdat er relatief weinig vrouwen in de steekproef zijn, is het moeilijk om percentages tussen geslachten te vergelijken wanneer beide grafieken dezelfde Y-asschaal gebruiken. Ik kan dat echter veranderen, dus elke grafiek gebruikt een aparte schaal door het argument toe scales = “free_y”te voegen aan de facet_wrap()functie:

ggplot (my_summary, aes (LanguageGroup, n, fill = Hobbyist)) +

geom_bar (stat = "identiteit") +

facet_wrap (facets = vars (geslacht), scales = "free_y")

Het is nu gemakkelijker om meerdere variabelen op geslacht te vergelijken.

Ga voor meer R-tips naar de "Do More With R" -pagina op of bekijk de "Do More With R" YouTube-afspeellijst.

Zie de volgende pagina voor informatie over het downloaden en verwarren van gegevens die in deze demo worden gebruikt.