-
Notifications
You must be signed in to change notification settings - Fork 0
/
Chapter1.Rnw
1269 lines (1047 loc) · 101 KB
/
Chapter1.Rnw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass[a4paper]{book}
%Title
\title{Aan de slag met \texttt{R}: Een kookboek en een kijkje in de keuken}
\author{Huub Hoofs}
%Griekse letters in tekst
\usepackage{textgreek}
%MmdFramed package (voor de tip blokken en borders voor fiugres)
\usepackage[tikz]{mdframed}
\setlength{\belowcaptionskip}{5pt plus 3pt minus 2pt}
\usepackage[font={sf},labelfont={bf,sf}]{caption}
%Inline blockquote
\usepackage[autostyle]{csquotes}
%Kleuren pakket
\usepackage{xcolor}
%Letters
\usepackage[latin1]{inputenc}
%Checkmark
\usepackage{pifont}% http://ctan.org/pkg/pifont
\newcommand{\cmark}{\ding{51}}%
\newcommand{\xmark}{\ding{55}}%
%Nogmaals TIKZ (ik denk dubbelop)
\usepackage{tikz}
%Opties voor tikz
\usetikzlibrary{shapes,arrows,matrix,positioning,calc,intersections,decorations.markings,fit}
%Taalpakket Nederlands
\usepackage[dutch]{babel}
%Pakket voor verschillende indexen
\usepackage[makeindex]{splitidx}
%Opmaak ander soortige texten
\usepackage{listings}
%Kleuren defineren zodat ze overeenkomen met knitrs defaults
\definecolor{newblue}{rgb}{.88, .92, .93}
\definecolor{newred}{rgb}{0.749,0.012,0.012}
\definecolor{textblue}{rgb}{0.004,0.004,0.506}
%Index voor voor tips and warnings and planning
\newindex[Tips \& Warnings]{tiw}
\newindex[Index]{pla}
%Plaatsing van H en andere float opties
\usepackage{float}
%Lege pagine figuur bovenaan
\makeatletter
\setlength{\@fptop}{0pt}
\makeatother
%Hyperref
\usepackage[breaklinks]{hyperref}
\hypersetup{
colorlinks,
citecolor=textblue,
filecolor=black,
linkcolor=textblue,
urlcolor=textblue
}
\usepackage{url}
%Tips e.d. boxen in een float plaatsen
\floatstyle{plain}
\newfloat{program}{!b}{lop}
\floatname{program}{Program}
%Float niet onder voetnoot
\usepackage[bottom]{footmisc}
\makeindex %https://mirror.hmc.edu/ctan/macros/latex/contrib/splitindex/splitidx.pdf
% $ latex Chapter1.tex
% $ splitindex Chapter1.idx
% $ makeindex Chappter1-pla.idx
% $ makeindex Chappter1-tiw.idx
% $ latex Chapter1.tex
% $ latex Chapter1.tex
% $ pdflatex Chapter1.tex
%%% Frames voor zowel tips als warnings door gberuik van tikz
\newcounter{tip}[section]
\newenvironment{tip}[1][]{%
\stepcounter{tip}%
\ifstrempty{#1}%
{\mdfsetup{%
frametitle={%
\tikz[baseline=(current bounding box.east),outer sep=0pt]
\node[anchor=east,rectangle,fill=textblue!20,draw=textblue,line width=2pt]
{\strut TIP~};}}
}%
{\mdfsetup{%
frametitle={%
\tikz[baseline=(current bounding box.east),outer sep=0pt]
\node[anchor=east,rectangle,fill=textblue!20,draw=textblue,line width=2pt]
{\strut \sindex[tiw]{#1}TIP:~#1};}}%
}%
\mdfsetup{innertopmargin=10pt,linecolor=textblue,%
linewidth=2pt,topline=true,splittopskip=2\topsep,
frametitleaboveskip=\dimexpr-\ht\strutbox\relax,}
\begin{program}\begin{mdframed}[]\relax%
}{\end{mdframed}\end{program}}
\newcounter{war}[section]
\newenvironment{war}[1][]{%
\stepcounter{war}%
\ifstrempty{#1}%
{\mdfsetup{%
frametitle={%
\tikz[baseline=(current bounding box.east),outer sep=0pt]
\node[anchor=east,rectangle,fill=newred!20,draw=newred,line width=2pt]
{\strut Pas Op:~};}}
}%
{\mdfsetup{%
frametitle={%
\tikz[baseline=(current bounding box.east),outer sep=0pt]
\node[anchor=east,rectangle,fill=newred!20,draw=newred,line width=2pt]
{\strut \sindex[tiw]{#1}Pas Op:~#1};}}%
}%
\mdfsetup{innertopmargin=10pt,linecolor=newred,%
linewidth=2pt,topline=true,splittopskip=2\topsep,
frametitleaboveskip=\dimexpr-\ht\strutbox\relax,}
\begin{program}\begin{mdframed}[]\relax%
}{\end{mdframed}\end{program}}
\renewcommand{\texttt}[2][textblue]{\textcolor{#1}{\ttfamily #2}}
\usepackage[os=win, mackeys=text]{menukeys}
%%% Mdframed omgeving voor figuren
\newenvironment{figframe}
{\mdfsetup{
topline=false,
rightline=false,
leftline=false,
linecolor=textblue,
linewidth=2pt
}
\begin{mdframed}%
}
{\end{mdframed}}
%%% Code to set up special term treatment
\makeatletter
\newcommand{\specialterms}[1]{%
\@for\next:=#1\do
{\@namedef{specialterm@\detokenize\expandafter{\next}}{}}%
}
\newcommand\term[1]{%
\@ifundefined{specialterm@\detokenize{#1}}
{\texttt[black]{#1}}{\texttt[textblue]{#1}\sindex[pla]{#1} \global\expandafter\let\csname specialterm@\detokenize{#1}\endcsname\relax}%
}
\makeatother
\specialterms{R,RStudio,foreign,diamanten,karakter,object,Usage,Inf,factor,numerieke,vector,element,logisische constanten,functie,Hmisc,matrix,data.frame,numeriek,lijst,t-toets,formula,car}
%%% Code to set up special func treatment
\makeatletter
\newcommand{\specialfunc}[1]{%
\@for\next:=#1\do
{\@namedef{specialfunc@\detokenize\expandafter{\next}}{}}%
}
\newcommand\func[1]{%
\@ifundefined{specialfunc@\detokenize{#1}}
{\texttt[black]{#1}}{\texttt[textblue]{#1}\sindex[pla]{#1@\textsl{#1}} \global\expandafter\let\csname specialfunc@\detokenize{#1}\endcsname\relax}%
}
\makeatother
\specialfunc{
require,library,read.spss,head,tail,ncol,nrow,dim,str,colnames,identical,subset,summary,rcorr,t.test
}
%Width
\usepackage[bindingoffset=0.5cm,margin=3.5cm]{geometry}
%Fancyhdr
%\renewcommand{\sectionmark}[1]{\markright{#1}}
%\renewcommand{\sectionmark}[1]{\markright{#1}}
\usepackage{emptypage}
\usepackage{fancyhdr}
\pagestyle{fancy}
\renewcommand{\chaptermark}[1]%
{\markboth{\ #1}{}}
\renewcommand{\sectionmark}[1]%
{\markright{\ #1}}
\fancyhead{}
\fancyfoot{}
\fancyhead[RE] {\rightmark\hspace{15pt}\thepage}
\fancyhead[LO] {\thepage\hspace{15pt}\leftmark}
<<settings, include=FALSE>>=
require(stringr)
require(knitr)
options(max.print=100, width=70)
op <- options(str = strOptions(strict.width = "wrap"))
thm <- knit_theme$get("edit-kwrite")
# thm <- knit_theme$get("biogoo")
# thm <- knit_theme$get("acid")
knit_theme$set(thm)
@
\begin{document}
\maketitle
\chapter*{Voorwoord}
Gateway drug
\tableofcontents
\chapter{Installeren}
Zoals in de introductie al wordt vermeld zal dit boek gaan voor een 'hands-on-approach'. Aan de einde van ieder hoofdstuk wordt echter ieder...
\section{Kookboek}
\subsection{\texttt[black]{R}}
Op de site van van \term{R}, {http://cran.rstudio.com}, staat een duidelijke instructie aangaande de installatie van \term{R} voor ieder besturingssysteem. Voor Windows klik je op \texttt{Download R for Windows} om vervolgens op \texttt{install R for the first time} te klikken. Hierna klik je op \texttt{Download R 3.X.X for Windows}, waar de getallen afhankelijk zijn van het huidige versie-nummer. Download het bestand. Vervolgens open je het bestand en zal er gevraagd worden in welke taal je het programma wil installeren.
\begin{tip}[Taal Keuze]
Persoonlijk adviseer ik altijd Engels omdat de meeste artikelen en oplossingen aangaande R nu eenmaal in het Engels zijn. Hierdoor wordt de kans op een bevredigend antwoord te vinden een stuk groter als je gebruik maakt van de (Engelstalige) terminologie die overeenkomt met de terminologie zoals deze op de meeste forums en website's wordt gebruikt.
\end{tip}
Vervolgens: Klik 3 maal op \menu{Next}. Bij de \texttt{Select Components} sectie selecteer de optie: \texttt{32-bit User installation} en klik op \menu{Next}. Klik vervolgens nog driemaal op \menu{Next} en tot slot op \menu{Finish}. R is nu ge\"installeerd.
\subsection{\texttt[black]{RStudio}}
Net als bij \term{R} is ook de site van \term{RStudio}, {http://www.rstudio.com}, zeer gebruiksvriendelijk. Klik op de home-page op de \texttt{Download Now}-knop en vervolgens op de \texttt{Download RStudio Desktop}-knop. Tot slot klik je op de link onder het kopje \texttt{Recommended For Your System}, bijv.: \directory{RStudio 0.XX.XXX - Windows XP/Vista/7/8}. Download het bestand en open het installatiebestand.
Vervolgens: \menu{Next} (3 maal). \term{RStudio} is nu ge\"installeerd en klaar voor gebruik.
\section{Kijkje in de keuken}
\subsection{\texttt[black]{R}}
De gebruikte link, {http://cran.rstudio.com}, is een mirror. Een mirror is een website waarop bestanden zijn te downloaden. Het spiegelt als het ware de bron, en om de bron niet over te belasten, wordt er gebruik gemaakt van verschillende spiegels. Als je je eigen mirror wilt kiezen is dit uiteraard mogelijk, ga hiervoor eerst naar {http://www.r-project.org/}, en klik vervolgens onder \texttt{Download, Packages} op \texttt{CRAN}. Nu zal je een lijst met landen zien, waarbij ieder land \'e\'en of meerderen mirrors heeft. Zoals te zien is de gebruikte link in de \texttt{kookboek}-sectie de 0-Cloud mirror, een soort overkoepelende mirror. Nederland heeft twee mirrors een van XL-Data Amsterdam, en een van Utrecht University. In de tijd van inbelinternet kon de keuze van de mirror van grote invloed zijn op de snelheid van downloaden, tegenwoordig is de invloed niet meer dan gering.
Bij het installeren van R zijn de eerste twee stappen vanzelfsprekend en is er geen keuze mogelijk. Bij de Select Destination Location, valt er echter voor het eerst wat te kiezen. In de \texttt{kookboek}-sectie wordt de gesuggereerde installatie locatie gebruikt. Het is echter ook mogelijk deze locatie aan te passen. Mocht je er dus belang aan hechten dat de installatie in een andere map (of schijf) plaatsvind dan is dat dus mogelijk. Hierbij is het echter wel aan te raden het einde van installatie locatie uitgang te laten staan (dus de installatie map altijd te laten eindigen op \texttt{\textbackslash{R}\textbackslash{R-3.X.X}}). Dit i.v.m. het gebruik van verschillende versies. In de volgende stap kan je de componenten kiezen die je wilt installeren, hierbij is een \texttt{32-bit User installation} het veiligst aangezien dit altijd werkt (zowel op een 32-Bits als 64-Bits Pc). Mocht je er echter zeker van zijn dat je een 64-bits PC hebt dan is deze optie ook bruikbaar. De keuze heeft geen invloed op de werking van R (alleen op de snelheid). Het is ook mogelijk om beide te installeren, dit kan echter verwarrend werken omdat beide versies volledig onafhankelijk van elkaar werken, en aanpassingen aan de 32-Bits versie dus niet worden overgenomen door de 64-Bits versie. Als je in de volgende stap voor \texttt{Yes (customized startup)} kiest, is het mogelijk om de interface (\texttt{MDI} vs. \texttt{SDI}) van R te veranderen, alsmede de manier waarop \textbf{Help-bestanden} worden getoond (\texttt{Plain text} vs. \texttt{HTML help}) en internet instellingen (\textbf{Standard} vs. \textbf{Internet2}). In de \texttt{Select Start Menu Folder} stap kan je R ook aan je startmenu toe voegen, dit is volledig optioneel. Als je hier geen behoefte aan hebt dan kan je de optie \texttt{Don't create a Start Menu folder} aanvinken. In de laatste stap (\texttt{Select Additional Tasks}) kan je aanvinken of je een R-pictogram op je bureaublad, respectievelijk, snelstartmenu wilt hebben. Deze twee pictogrammen zijn, gelijk aan de vorige stap, volledig optioneel. Het is wel sterk aan te bevelen om de twee \texttt{Regirstry entries} aan te vinken. De eerste keuze (\texttt{Save version number in registry}) zorgt voor een overzichtelijk versie beheer. De tweede keuze zorgt ervoor dat bestanden met een \texttt{.R} of \texttt{.RData} worden geassocieerd met R.
\subsection{\texttt[black]{RStudio}}
De opties voor de installatie van \term{RStudio} zijn een stuk minder uitgebreid. De enige keuzes dier er zijn betreffen de locatie waar je \term{RStudio} wilt installeren en het eventueel cree\"eren van een Snelkoppeling. Ook deze keuzes zijn volledig optioneel.
\begin{war}[Alternatieve installatie locatie]
Als je er voor hebt gekozen om bij de installatie af te wijken van de gesuggereerde locatie dan is het mogelijk dat \term{RStudio} \term{R} niet kan 'vinden'. In dit geval zal er een pop-up menu getoond worden als je \term{RStudio} opent. Kies hierbij de optie \texttt{Choose a specific version of R} en vervolgens \texttt{Browse}. Navigeer naar de locatie waar R is ge\"installeerd en kies \texttt{select folder}. \term{RStudio} zal nu onthouden waar R is ge\"installeerd en iedere volgende keer R starten vanuit deze locatie.
\end{war}
\chapter{Data Inlezen}
\section{Kookboek}
\subsection{\texttt[black]{foreign}-Pakket installeren \& activeren}\label{sec:DataKookForeign}
Om data van andere statistische programma's in te lezen hebben het \term{foreign} \term{pakket} nodig. Eerst moeten we dit pakket installeren. Klik hiervoor op \menu{Packages > Install Packages} en type onder \menu{Packages (seperate multiple with space or comma)} \directory{foreign} en vervolgens op \menu{Install}. Het \term{foreign}-pakket is nu ge\"installeerd.
Vervolgens moet het pakket worden ingeladen, hiervoor moet we eerst een nieuw script openen van waaruit we alle commando's gaan uitvoeren. Klik hiervoor op \menu{File > New File > R Script}. Vervolgens verschijnt er een venster met als titel \texttt{Untitled1}. Vervolgens typen we in dit script onze eerste syntax.
<<label="foreignsyntax", echo=TRUE, eval=FALSE>>=
require(foreign)
@
Om deze regel syntax uit te voeren zijn er verschillende mogelijkheden:Zo is het mogelijk de syntax te markeren en vervolgens (i) op \menu{Run} te klikken, (ii) de toetsencombinatie \keys{ctrl + enter} te gebruiken, of (iii) het menu \menu{Code > Run Line(s)} gebruiken. Bij deze methode zal alle gemarkeerde syntax worden uitgevoerd. Het is echter ook mogelijk om ergens op de regel te klikken en vervolgens een van de drie bovengenoemde methodes toe te passen. Deze methode voert vervolgens de syntax uit die op deze regel is gegeven.
Kies een van de bovengenoemde methodes en voer te syntax uit. Je zult nu het volgende in de \texttt{Console} zien verschijnen
<<label="foreignconsole", echo=TRUE>>=
require(foreign)
@
Het \term{foreign}-pakket is nu actief.
\begin{tip}[Pakketen installeren en activeren]
Het installeren van een pakket is slechts eenmaal nodig. Het activeren van een pakket moet echter wel iedere keer opnieuwe herhaald worden wanneer \term{RStudio} wordt opgestart. Dit activeren hoeft echter maar eenmaal binnen dezelfde sessie te worden uitegevoerd. Als je de bovengenoemde syntax nogmaals uitvoert zul je ook zien dat er geen melding meer verschijnt. Dit komt omdat het pakket al is geactiveerd!
\end{tip}
\subsection{Werkmap}
Voor \term{R} is het van belang om te weten in welke map de bestanden e.d. staan die je wilt gebruiken. Deze map wordt de werkmap genoemd. Alle verwijzingen naar bestanden zijn altijd relatief ten op zichte van de werkmap, zoals we later zullen zien. Eerst is het van belang om de werkmap de defineren. Klik hiervoor op \menu{Files > \dots} en navigeer naar de map waar je het SPSS bestand hebt opgeslagen en klik vervolgens op \menu{Ok}. Nu zal je onder \menu{Files} alle bestanden zien die zich in de door jouw gespecifeerde map bevinden. Dit is echter pas de helft van het verhaal, om deze map als werkmap te defineren is er nog een handeling nodig, klik hiervoor op \menu{Files > More > Set As Working Directory}. Je zal nu iets als het volgende in de \texttt{Console} te zien krijgen:
<<label="consolesetwd", echo=TRUE, eval=FALSE>>=
setwd("D:/Users/Huub/Documents/Project/GettingThingsR")
@
Om te controleren of je werkmap inderdaad juist is gedefineerd type je het volgende in je syntax:
<<label="sourcegetwd", echo=TRUE, eval=FALSE>>=
getwd()
@
En voer je dit commando uit (bijv. \keys{ctrl + enter})
<<label="consolegetwd", echo=TRUE, eval=TRUE>>=
getwd()
@
In de \texttt{Console} is nu te zien welke map als werkmap is gedifineerd. Er is echter een klein verschil met de daadwerkelijke weergave op het scherm, aangezien dat er als volgt uit zal zien:
<<label="consolegetwdactual", echo=FALSE, eval=TRUE, comment=NA>>=
cat(c('> getwd()','[1] "C:/Users/HuCa/Documents/GettingThingsR"'),sep="\n")
@
De \keys{\textgreater} wordt echter weggelaten omdat op deze manier de syntax makkelijker te kopieren is (anders zou de \keys{\textgreater} worden meegekopierd en werkt de syntax niet). Deze invoer is dus precies hetzelfde als de geactiveerde syntax. In principe is het ook mogelijk om alles direct in de \texttt{Console} te typen, maar dit is niet bevordelijk voor de reproduceerbaarheid en gebruiksgemak van \term{R} en daarom wordt deze methode niet toegepast in dit boek. Het andere verschil zit in de toevoeging van \keys{\#\#} voor iedere lijn uitvoer. Hierdoor is de uitvoer en invoer makkelijk te scheiden van elkaar. Er is hier voor \keys{\#\#} gekozen omdat alle invoer die hierna volgt in de syntax, genegeerd wordt door \term{R} (zie verder de tip op pagina \pageref{tip:opm}). Hierdoor is het dus mogelijk ieder blok in zijn geheel naar de syntax te kopieren en uit te voeren.
\begin{tip}[Definering werkmap opnemen in syntax]
Zoals je kunt zien hebben we het commando:
<<label="consolesetwd2", echo=TRUE, eval=FALSE>>=
setwd("D:/Users/Huub/Documents/Project/GettingThingsR")
@
\noindent
niet opgenomen in de syntax. Dit is echter wel aan te bevelen. Dit komt voornamelijk omdat, net als de pakketen, je de werkmap bij iedere nieuwe \term{R} sessie opnieuw moet defineren. Nu is het natuurlijk mogelijk om dit iedere keer volgens de hierboven beschreven methode te doen, maar het is handiger om het commando zoals te zien in de \texttt{Console}, bovin je syntax te kopieren. Op deze manier is het eerste wat je doet bij het uitvoeren van je syntax het defineren van je werkmap. Omdat alle bestandlocaties t.o.v. de werkmap worden gezien is deze juiste definering van de werkmap cruciaal!
\end{tip}
\subsection{Inlezen SPSS-bestand}
Nu het juiste pakket en de werkmap is gedefineerd kunnen we beginnen om het SPSS-bestand in te lezen. Hiervoor gebruiken we een functie uit het \term{foreign}-pakket. \textbf{Vanaf nu wordt de syntax en de bijbehorende resultaat uit de \texttt{Console} gelijkertijd weergegeven.}
<<label="diamantenSav", tidy=TRUE, highlight=TRUE, warning=FALSE>>=
read.spss(file="diamanten.sav", to.data.frame=TRUE)
@
Het is mogelijk dat er een \texttt[newred]{Warning message} in de \texttt{Console} komt, deze kan je echter negeren. Zoals je ziet krijg je de eerste regels (aantal verschilt per PC) te zien van het databestand. \term{R} laat altijd maar een beperkt aantal regels zien om de \texttt{Console} overzichtelijk te houden. Het is ons nu dus gelukt om een SPSS-bestand te lezen met behulpt van \term{R}. Er is echter \'e\'en probleem! Als we met dit databestand willen gaan werken zouden we iedere keer de zojuist gebruikte functie (\texttt{read.spss}) te gebruiken. Dit is natuurlijk erg omslachtig en hier is dan ook een zeer nuttige oplossing voor: Het cree\"eren van een \textbf{object}.
Een object kan alles zijn dus ook een databestand. Om een object te creeren gebruiken we \keys{\textless + -}. Daarnaast moet een object ook een naam hebben, welke je gebruikt om het object 'op te roepen'. Laten we het diamanten bestand linken aan een object onder de naam \term{diamanten}, door de vorige syntax aan te passen:
<<label="diamantenAssignObject", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten <- read.spss(file="diamanten.sav", to.data.frame=TRUE)
@
Zoals je ziet is er in de \texttt{Console} nu niks anders te zien dan de syntax (en misschien een \texttt[newred]{Warning message}). Maar dat betekend niet dat er niks gebeurd is! Want als je nu alleen de naam van het object typt:
<<label="diamantennObject", tidy=TRUE, highlight=TRUE, warning=FALSE>>=
diamanten
@
Krijg je te zien dat het object \term{diamanten} gelijk staat aan het databestand. Doordat we objecten gebruiken is het echter handiger om niet meer over databestanden te spreken maar over dataframe's of dataobjecten. Het object \term{diamanten} is immers geen losstaand bestand maar is toegevoegd aan de \term{R}-omgeving, \texttt{Environment} genoemd in \term{RStudio}. Nu we het dataframe hebben toegevoegd aan de \texttt{Environment} kunnen we er in het volgende hoofdstuk van alles mee gaan doen!
\begin{war}[Hoofdlettergevoelig]
\term{R} is hoofdlettergevoelig, als een object dus \term{diamanten} heet dan zal je een foutmelding krijgen als je \texttt[black]{Diamanten} gebruikt:
<<label="DiamantenObject", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
Diamanten
@
Dit telt voor alle bewerkingen in \term{R}, functies, locaties van databestanden, waardes, etc.
\end{war}
\section{Kijkje in de keuken}
\subsection{\texttt[black]{foreign}-Pakket installeren \& activeren}
Het is van belang om te begrijpen dat \term{R} eigenlijk niet meer is dan een programmeertaal. In tegenstelling tot de meeste andere programmeertalen kenmerkt \term{R} zich echter door een aantal voorgeschreven functies waarmee basale (statistische) bewerkingen kunnen uitvoeren worden uitgevoerd. Het is vooral deze balans die er voor zorgt dat \term{R} een stuk krachtiger en flexibeler is dan andere statistiek programma's zoals SPSS, maar tegelijkertijd toegangelijker is dan pure programmeertalen zoals \texttt{Python}.
Aangezien \term{R} echter werkt met een open-code (open-source), is het voor iedereen mogelijk toevoegingen in de vorm van pakketten te ontwerpen en deze in te dienen. Als een pakket is goedgekeurd dan wordt deze beschikbaar gesteld via het offici\"ele CRAN (Comprehensive R Archive Network) archief.\footnote{Het is echter ook mogelijk dat je pakketten op internet vind die niet via de offici\"ele manier worden aangeboden. Dit zijn meestal kleine aanpassingen op bestaande pakketten, maar ook grotere pakketen worden soms op deze manier aangeboden. Deze pakketen kunnen uiteraard prima werken, toch is de controle (vooral van de \term{R}-gemeenschap) bij dergelijke pakketten een stuk lager, dus waakzaamheid is aan te raden!} Het voordeel van deze, semi-gecontroleerde, manier van pakket-distrubutie is dat de kwaliteit gewaarborgd blijft. Daarnaast is het ook verplicht dat ieder pakket een uitgebreide handleiding heeft waarin iedere functie uitgebreid wordt beschreven. Daarnaast werken alle pakketten op hun beurt ook weer met een open-code, waardoor eventuele fouten snel kunnen worden opgespoord en hersteld.
Nu het hoe en waarom van pakketen is uitgelegd, kunnen we ons concentreren op de installatie ervan. Zoals vermeld is dit eenvoudig mogelijk via \menu{Packages > Install Packages}, het is echter ook mogelijk om een installatie via de syntax uit te voeren. Deze methode is ook zichtbaar als je een pakket installeerd via de zojuist genoemde methode. Als je deze methode namelijk volgt zal je in \texttt{Console} de volgende invoer zien:
<<label="InstallSyntaxx", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
install.packages("foreign")
@
Echter, zoals vermeld staat bij de Tip aangaande het installeren van pakketten is installatie van een pakket slechts per PC slechts een keer nodig. Daarom is het voor de reproduceerbaarheid van de \texttt{syntax} geen must om het hierin op te nemen. Wat dus wel een must is voor de repoduceerbaarheid is het includeren van in de syntax van het inladen van het pakket. Naast de gebruikte functie \func{require} is het ook mogelijk de functie \func{library} te gebruiken--er zit geen enkel verschil tussen beiden.
\subsection{Werkmap}
Het defineren van een werkmap is relatief eenvoudig. Zoals vermeld zal \term{R} altijd vanuit deze map werken. Als bestanden worden ingelezen of worden opgeslagen zal dat dus vanuit deze werkmap plaatsvinden. Het is echter ook mogelijk om bij dergelijke bewerkingen af te wijken van de werkmap. Het kan bijvoorbeeld voorkomen dat een databestand op een andere locatie staat en dat het van belang is dat deze locatie niet wordt veranderd. Bij een dergelijk geval zal deze locatie moeten worden vermeld bij het gebruik van een functie. Stel bijvoorbeeld dat het \term{diamanten}-bestand op een andere locatie staat dan in de werkmap dan zou de \texttt{syntax} er bijvoorbeeld als volgt uit kunnen zien:
<<label="diamantenAssignObjectOther", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
read.spss(file="D:/Users/Huub/Documents/OverigeMap/diamanten.sav",
to.data.frame=TRUE)
# i.p.v. read.spss(file="diamanten.sav",to.data.frame=TRUE)
@
Zoals je ziet is dit een stuk omslachtiger, en daarom verdient het ook de voorkeur om zoveel mogelijk vanuit de werkmap de werken. Een bijkomend voordeel is dat als de locatie van de werkmap veranderd (bijvoorbeeld naar een andere PC), alleen de werkmap opnieuw hoeft te worden gedefineerd.
\begin{war}[\textbackslash\textbackslash of /, maar niet \textbackslash]
Een optie om de werkmap de defineren is natuurlijk de locatie te kopieren vanuit bijvoorbeeld Windows Explorer te kopi\"eren. Dat zou er dan als volgt uit zien:
<<label="workingdirectoryW", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE, error=TRUE>>=
setwd("D:\Users\Huub\Documents\Project\GettingThingsR")
@
\noindent
Error?! Maar wat is dan het verschil met de juiste invoer? Het verschil zit hem in de \textbackslash. Zoals veel programma's gebruikt \term{R} de \textbackslash als een bijzonder invoerteken. Oftewel het maakt onderdeel uit van bepaalde bewerkingen. In dit voorbeeld probeert \term{R} de bewerking \textbackslash{U}, wat geen geldige bewerking is. Het is daarom van belang altijd een van de volgende twee variaties te gebruiken:
<<label="workingdirectoryAlt", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
setwd("D:\\Users\\Huub\\Documents\\Project\\GettingThingsR")
setwd("D:/Users/Huub/Documents/Project/GettingThingsR")
@
\noindent
Dus of een dubbele \textbackslash, of simpelweg een enkele /.
\end{war}
\subsection{Inlezen SPSS-bestand}
Bij het inlezen van een bestand maken we eigenlijk voor het eerst echt gebruik van een functie (ook al is \func{require} ook een functie). Aangezien functies een belangrijk onderdeel vormen van \term{R} is een goed begrip van functies esssentieel. Een functie heeft altijd een bepaalde invoer nodig. Wat voor een invoer dat is ligt aan de functie. Als er een gemiddelde moet worden berekend moeten het getallen zijn, als er een databestand moet worden ingelezen moet het de naam van het bestand zijn.
De invoer van een functie kan bestaan uit meerdere elementen die allemaal een eigen functie hebben binnen de functie. Zo bestaat functie \func{read.spss} uit de volgende elementen:
<<label="readspssFunctie", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
read.spss(file, use.value.labels = TRUE, to.data.frame = FALSE,
max.value.labels = Inf, trim.factor.names = FALSE,
trim_values = TRUE, reencode = NA,
use.missings = to.data.frame)
@
Zoals je ziet zijn dit meer elementen dan dat we hebben gebruikt om het databestand in te lezen\ldots Hoe kan dit? Dit kan omdat sommige elementen een standaard waarde hebben. Zo kan je zien dat het element \texttt{use.value.labels} een standaard waarde van \texttt{TRUE}. Aangezien we de waarde voor dit element niet hebben gespecificeerd zal het dus de standaard waarde (\texttt{TRUE}) aannnemen. Het is mogelijk om het element zelf te specificeren met de standaard waarde, maar dit zal dus geen effect hebben op de werking van de functie. De enige elementen die je dus moet specificeren zijn dus elementen die geen standaard waarde hebben of elementen waar je van de standaard waarde wilt afwijken.
In de \func{read.spss} functie hebben we in het voorbeeld daarom de elementen \texttt{file} en \texttt{to.data.frame} gefineerd. Waarbij de eerste geen standaard waarde heeft en de tweede als standaard waarde \texttt{FALSE} heeft terwijl de voorkeur hier naar \texttt{TRUE} uitgaat. Als het goed is blijf je nu met twee vragen zitten. Hoe weet ik welke elementen een functie bevat, en hoe weet ik of een element een standaard waarde heeft?
Om de elementen van een functie te weten te komen is het nodig om de help functie te gebruiken. Dit is redelijk eenvoudig, je zet namelijk simpelweg een \keys{?} voor de functie:
<<label="questionReadspss", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
?read.spss
@
Nu zal je zien dat er onder \texttt{Help} een tekst komt te staan waar de functie wordt toegelicht. Het eerste kopje, \emph{Description} bevat een (korte) omschrijving van de functie. Waar het echter om gaat zijn de volgende twee kopjes, \emph{Usage} en \emph{Arguments}. Het eerste kopje geeft namelijk aan welke elementen de functie bevat en het tweede kopje geeft een toelichting op een ider van deze elementen. Zo moet het eerste element (\texttt{file}) dus bestaan uit \term{karakter}-reeks die aangeeft waar het bestand zich bevind. Het andere element dat we hebben aangepast is \texttt{to.data.frame} wat aangeeft of we een dataframe als \term{object} willen terugkrijgen of niet.
De overige kopjes geven extra informatie, die vaak erg handig kan zijn. Zo geeft \emph{Details} een gedetailleerde beschrijving van de werking van de functie. \emph{Value} Geeft aan wat voor een soort uitvoer de functie geeft. \emph{Value} betreft dus uitvoer en \emph{Arguments} invoer. De kopjes \emph{Note}, \emph{Author(s)}, en \emph{See Also} spreken voor zich. Tot slot is er het kopje \emph{Examples}, wat meestal erg verduidelijkend werkt, door voorbeelden te geven hoe de functie kan worden gebruikt.
Nu we weten hoe de functie eruit ziet en wat het doet, blijft alleen de vraag nog staan hoe we kunnen weten welk element een standaard waarde heeft en welke niet. Soms is dit vermeld onder \emph{Arguments}, maar je kan het altijd terug zien onder \term{Usage}. Hierbij heeft een element dat gevolgt wordt door een \keys{=}, een standaard waarde. De standaard waarde, je raadt het al, is de waarde achter het \keys{=}-teken. Dus het element \texttt{max.value.labels} heeft dus een standaard waarde van \term{Inf}, wat gelijk staat aan oneindig (\emph{infinite}). Als we zit combineren met de informatie die onder \emph{Arguments} staat kunnen we dus redelijk ontleden wat dit element doet, en wat er gebeurd als we het niet specificeren. Hier gaat het dus om het aantal unieke waardes dat een variabele mag hebben om te worden omgecodeerd tot een \term{factor}. Waarbij de standaard waarde oneindig betreft.
Een laaste opmerking die gemaakt dient te worden ten opzichte van een functie is dat de volgorde waarin je de elementen ordent niet uitmaakt. Het volgende is dus ook mogelijk:
<<label="MirroredFunction", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
read.spss(to.data.frame=TRUE, file=("diamanten.sav")
# i.p.v. read.spss(file="diamanten.sav", to.data.frame=TRUE)
@
\begin{figure}[h]
\begin{figframe}
\centering
% Define block styles http://www.texample.net/tikz/examples/simple-flow-chart/
\tikzstyle{block} = [rectangle, draw=textblue, fill=textblue!20,
text width=5em, text centered,line width=2pt, minimum height=4em]
\tikzstyle{line} = [draw, -latex',line width=1pt]
%Picture
\begin{tikzpicture}[node distance = 2cm, auto, font=\sffamily]
% Place nodes
\node [block] (pak) {Pakketten};
\node [block, below of=pak, node distance=3.5cm] (func) {Functies};
\node [block, right of =func, node distance=6cm] (elem) {Element};
\node [block, below of=func, node distance=3.5cm] (waar) {Waarde};
\node [block, below of=elem, node distance=3.5cm] (obj) {Object};
% Draw edges
\path [line] (pak) -- node [anchor=center, fill=white,align=center] {Functie 1\\ Functie\ldots} (func);
\path [line] (elem) -- node [anchor=center, fill=white,align=center] {Invoer} (func);
\path [line] (func) -- node [anchor=west, rotate=330,fill=white,align=center,xshift=0.15cm] {Bewerking} (obj);
\path [line,dashed] (func) -- node [anchor=center,fill=white,align=center] {Standaard\\waardes} (waar);
\path [line] (waar) -- (elem);
\end{tikzpicture}
\caption{Schematische weergave van de werking van functies in \term{R}.} \label{fig:schemaR}
\end{figframe}
\end{figure}
Nu we hebben gekeken hoe we de werking en inhoud (elementen) van een functie kunnen bekijken, is het van belang om nog even kort stil te staan bij de invoer van de bestandsnaam. Zoals we hebben gezien moest \texttt{file} een \term{karakter}-reeks bevatten, wat zoveel betekend als een stuk tekst. Een \term{karakter}-reeks kan echter ook bestaan uit enkel cijfers, maar toch worden gezien als een \term{karakter}-reeks, bijvoorbeeld:
<<label="characterNumbers", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
# Karakter-reeks
"123"
# Numeriek
123
@
Het verschil zit hem dus in de \keys{''}. Alles wat tussen twee leeshaakjes wordt geplaatst is dus een \term{karakter}-reeks. Het maakt trouwens niet uit of je \keys{'} of \keys{''} gebruikt, als je de \term{karakter}-reeks maar afsluit waarmee je bent begonnen.
Tot slot spelen de waardes \texttt{TRUE}/\texttt{FALSE} een belangrijke rol in \term{R}.\footnote{\texttt{TRUE}/\texttt{FALSE} moet altijd met hoofdletters worden geschreven, daarnaast is ook mogelijk om als vervanging \texttt{T}/\texttt{F} te gebruiken maar dit is niet aan te raden!} Waarbij \texttt{TRUE} als het ware goedkeuring geeft aan een element en \texttt{FALSE} het tegenovergestelde effect heeft.
\begin{tip}[Verkorte invoer functie]
Tot nu toe worden alle functies netjes uitgeschreven. Het is in bepaalde gevallen ook mogelijk alleen de invoer te plaatsen. Dat ziet er als volgt uit:
<<label="ShortFunction", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
read.spss("diamanten.sav", to.data.frame=TRUE)
# i.p.v. read.spss(file="diamanten.sav", to.data.frame=TRUE)
@
\noindent
Zoals je ziet wordt het stukje \texttt{file=} achterwegen gelaten, maar het stukje \texttt{to.data.frame=} niet, hoe zit dat?
\indent
De naam van het element kan worden weggelaten als de volgorde van invoer overeenkomt met de standaard volgorde van de functie. Aangezien \texttt{\char`\"diamanten.sav\char`\"} dus het eerste stukje invoer is wordt dus dit dus automatische gelinkt aan het eerste element (\texttt{file}) van de functie (onthoud \texttt{?read.spss}). Daarom is het ook niet mogelijk om de volgende, nog kortere, variant te gebruiken:
<<label="ToShortFunction", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
read.spss("diamanten.sav", TRUE)
@
Hier wordt \texttt{TRUE} namelijk toegewezen aan het tweede element (\texttt{use.value.labels}), terwijl wij het aan het derde element willen toewijzen. Als je dus van de standaard volgorde afwijkt moet je de element naam toevoegen aan de syntax van de functie.
In dit boek zullen elementnamen altijd worden vermeld in de functie. Dit heeft als voornaamste functie duidelijkheid, maar het bevorderd ook een overzichtelijke \texttt{syntax}, het is immers goed mogelijk dat je niet meer uit je hoofd weet wat ook al weer de standaard volgorde van elementen was in een functie.
\end{tip}
\chapter{Beschrijvende statistiek \& Data bewerking}
\section{Kookboek}
\subsection{Datastructuur}
In eerst instantie is het vaak prettig om wat meer gevoel met het dataframe te krijgen. In tegenstelling tot SPSS bijvoorbeeld zien we niet meer direct de spreadsheet, wat in het begin toch even wennen is! De eerste methode om de data wat verder te bekijken is om onder \texttt{Environment} op \term{diamanten} te klikken. Nu zal er op de plaats waar eerst de syntax stond een soort van Excel-sheet te staan. In tegenstelling tot een Excel-sheet is het echter niet mogelijk om de getallen te bewerken, het is dus puur ter controle. Daarnaast is ook dit overzicht tot een maximum aantal lijnen beperkt. Waar zijn die onderste lijnen toch gebleven? Simpel:
<<label="DiamantenTail", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
tail(x=diamanten)
@
Met deze functie is het mogelijk om de laatste vijf lijnen te zien van het dataframe. Daarnaast geven de nummers voor iedere lijn ook aan welk rijnummer de de rijen hebben t.o.v. van het totale dataframe. Een tegenovergestelde functie is ook beschikbaar:
<<label="DiamantenHead", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
head(x=diamanten)
@
Nu de eerste en laatste rijen bekend zijn, zijn er nog een aantal ander functies die een overzicht geven de structuur van de data, zoals onder andere het aantal rijen, kolommen, of beide:
<<label="DimensiesDiamanten", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
nrow(x=diamanten) #Aantal rijen
ncol(x=diamanten) #Aantal kolommen
dim(x=diamanten) #Aantal dimensies
@
Het aantal rijen en kolommen komt, zoals verwacht, overeen met het aantal van het SPSS-bestand. Een laatste handige methode om zicht te krijgen op de structuur van je data is de \texttt{str} functie:
<<label="StrDiamanten", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
#Overzicht structuur
str(object=diamanten)
@
Deze functie geeft voor iedere variabele (kolom) aan wat voor een soort variabele het is en geeft een aantal unieke waardes voor iedere variabele. Zoals te zien is bijvoorbeeld de variabele \texttt{cut} een \term{factor} met 5 mogelijke waardes (waarvan twee voorbeelden worden gegegeven: ''Fair'' \& ''Good''). De variabele \texttt{depth} daarintegen is een numerieke variabele. De vorm van de variabele be\"invloedt de mogelijke bewerkingen die met de variabele mogelijk zijn.
Tot slot is het som handig om alleen de variabele namen van het dataframe te zien, daarvoor kan je simpelweg de volgende functie gebruiken:
<<label="ColNames", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
colnames(x=diamanten)
@
\begin{tip}[Opmerkingen \#]
Zoals je ziet wordt alle input na een \# genegeerd door de \texttt{Console}. Tekst naar een \# kan daarom ook gezien worden als een opmerking. Dit is uiteraard handig als je de syntax enigzins overzichtelijk wilt maken. Het maakt niet uit wat je naar het \# doet, een opmerking hoeft dus niet afgesloten te worden. Als je echter over meerdere lijnen een opmerking wilt maken is het wel van belang om iedere lijn te beginnen met een \#. \label{tip:opm}
\end{tip}
\subsection{Object manipulatie}
Een kleine introductie tot \term{object} manipulatie is onontkoombaar om \term{R} effici\"ent te gebruiken. Het is bijvoorbeeld nodig om beschrijvende statistiek te verkrijgen van een selectie van variabelen, i.p.v. alle variabelen. Daarnaast gebruik ik bewust de bewoording ''\term{object}-manipulatie'' t.o.v. ''Dataframe-manipulatie'', omdat de manipulatie methodes niet alleen toegepast kunnen worden op dataframes maar op objecten in het algemeen.
Laten we eerst kijken naar de mogelijkheid om \'e\'en enkele variabele selecteren. Hiervoor zijn verschillende methode's waarvan we hier er twee zullen toelichten. De eerste methode maakt gebruik van het \keys{\$}-teken, dit wordt toegepast als volgt:
<<label="DollarDiamanten", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten$carat
@
Het onderdeel met de naam vermeld na het \keys{\$}-teken wordt dus ontrokken uit het \term{object} voor het \keys{\$}-teken. Het resultaat is een vector, wat niks meer is dan een rij van waardes (in dit geval cijfers), ofwel een dataframe met slechts een kolom.
De tweede optie maakt gebruik van de \keys{\lbrack + \rbrack}-tekens. De uitwerking van de deze optie ziet er als volgt uit:
<<label="BrackDiamanten", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten[,c("carat")]
@
Dat ziet er een stuk ingewikkelder uit! Maar deze methode heeft zijn winst echter liggen in de mogelijkheid tot uitbreiding. Zo is het bijvoorbeeld mogelijk om meerdere kolommen tegelijk te selecteren:
<<label="BrackDiamantenMultiple", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=2>>=
options(max.print=20)
diamanten[,c("carat","color")]
@
Naast het selecteren van kolommen is ook mogelijk om rijen te selecteren, zo is het mogelijk om de eerste 5 rijen te selecteren:
<<label="BrackDiamantenRow5", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=2>>=
options(max.print=100)
diamanten[1:5,]
@
Waarbij beide methode's ook gecombineerd kunnen worden:
<<label="BrackDiamantenRowKolom", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten[20:25,c("color","table")]
@
Hier worden dus rij 20 t/m 25 geselecteerd voor de variabelen \texttt{color} \& \texttt{table}. De laatste functie die we in dit stuk bespreken is de \texttt{subset}-functie. Deze functie zorgt ervoor dat alleen de rijen (\emph{cases}) die voldoen aan een bepaalde voorwaarde worden geselecteerd. Stel dat we bijvoorbeeld alleen maar de rijen willen selecter waarvan de \texttt{cut} 'Very Good' is, dan kan dat als volgt:
<<label="SubsetExamp", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
subset(x=diamanten, subset=cut=="Very Good")
@
Hierop zijn natuurlijk talloze variaties mogelijk, die in de \textbf{Kijkje in de keuken}-sectie verder worden toegelicht. Wel is het benoemingswaardig dat de rijnummers worden getoond van het orginele dataframe, de eerste rij die dus voldoet aan het gekozen criteria is dus de 6\textsuperscript{e} rij.
\subsection{Beschrijvende statistiek}
Een goede start is de \texttt{summary}-functie. Deze kan je bijvoorbeeld toepassen op het hele dataframe:
<<label="SummaryDiamant", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=100)
summary(diamanten)
@
Voor \term{numerieke}-variabelen wordt het minumim, 1\textsuperscript{e} kwartiel, mediaan, gemiddelde, 3\textsuperscript{e} kwartiel en maximum getoond. Voor \term{factor}- en \term{karakter}-variabelen worden de meest frequente waardes getoond.
Het is natuurlijk ook mogelijk om per variabele verschillende waardes te bekijken, voor numerieke variabelen zijn er bijvoorbeeld de volgende mogelijkheden:
<<label="NumeriekeMogelijkheden", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
mean(x=diamanten$carat, na.rm=TRUE) #Gemiddelde
sd(x=diamanten$carat, na.rm=TRUE) #Standaard deviatie
min(x=diamanten$carat, na.rm=TRUE) #Minimum
max(x=diamanten$carat, na.rm=TRUE) #Maximum
@
\begin{war}[na.rm=TRUE]
Waarom staat er bij de meeste simpele functie al een rare toevoeging in de vorm van \texttt{na.rm=TRUE}. In het bovenstaande geval werken de functies ook zonder deze toevoeging, echter als de variabele \'e\'en of meerdere missende waardes bevat (aangeveven met \texttt{NA}) dan is deze toevoeging wel cruciaal. De toevoeging staat namelijk voor ''Missing at random''. Als dit niet waar is, FALSE (de standaardwaarde in deze functie), is het niet mogelijk om een gemiddelde te berekenen:
<<label="MissingMean", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
Var1 <- c(0,2,4,6,8,10,NA)
# Vergelijk
mean(x=Var1, na.rm=TRUE)
mean(x=Var1) #gelijk aan mean(x=Var1, na.rm=FALSE)
@
\end{war}
Voor \term{factor}- en \term{karakter}-variabelen zijn behoren de volgende opties tot de mogelijkheden:
<<label="KarakterMogelijkheden", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
table(diamanten$cut) #Frequenties van iedere waarde
prop.table(table(diamanten$cut)) #Relatieve proporties per waarde
prop.table(table(diamanten$cut))*100 #als percentage
@
Tot slot kijken we nog naar de basis functie voor de correlatie:
<<label="CorrelatieDiamanten", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
cor(diamanten[ ,c("depth","table","price")])
@
Waarbij hier dus de correlatie voor de variabelen \texttt{depth}, \texttt{table}, en \texttt{price} worden gegeven.
\section{Kijkje in de keuken}
\subsection{Datastructuur}
Zoals we in het voorgaande hoofdstuk hebben kunnen zien, is het niet nodig om elementen van een functie te defineren als deze een standaardwaarde hebben. Als een dergelijk element niet wordt gedefineerd zal de functie immers deze standaardwaarde gebruiken om de functie uit te voeren. Ook bij de functies \func{head} en \func{tail} maakten we hier in het kookboek gebruik van. In het kookboek werd aangegeven dat deze functie de eerste (of laatste) 6 rijen van een dataframe laat zien. Als we echter kijken naar de elementen van deze functies (\texttt{?head} of \texttt{?tail}) zien we dat we dit aantal kunnen aanpassen door een waarde aan het element \texttt{n} toe te wijzen. Standaard is dit getal \texttt{6},\footnote{Zoals je in het \texttt{Help}-bestand kan zien is de standaardwaarde \texttt{6L} i.p.v. \texttt{6}. Deze \texttt{L} zorgt ervoor dat deze 6 als een geheel getal wordt gedefineerd. Voor de werking van de functie maakt het niks uit, het enige verschil is dat bewerkingen van dergelijke ''hele'' getallen ietsjes sneller zijn dan van ''normale'' getallen. Wil je zeker weten dat een \texttt{6} gelijk is aan \texttt{6L}, vraag het aan \term{R} zelf (\texttt{6 == 6L}).} als we dit echter veranderen in \texttt{3} dan zullen alleen de eerste (of laatste) drie rijen worden getoond:
<<label="DiamantenHead3Rows", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
head(x=diamanten, n=3)
# versimpeld; head(diamanten, 3)
@
De fucnties \func{ncol}, \func{nrow} en \func{dim} hebben geen alternatieve elementen, en hebben dus ook geen variaties op de manier waarop ze zijn uitgevoerd in het kookboek. De functiesen \func{str} heeft daarentegen zeer veel optionele elementen, deze zijn echter niet belangrijk voor het hoofddoel van deze functie, overzicht krijgen. Mocht je toch geintreseerd zijn, dan weet je wat je moet doen: \texttt{?str}.
Een stuk intressanter zijn echter de mogelijkheden die \func{colnames} biedt. Twee aspecten zijn van belang om deze mogelijkheden te begrijpen. Het eerste aspect betreft het soort object dat deze functie als uitvoer geeft, een \term{vector}. Een \term{vector} is een reeks van \'e\'en bepaald soort waarde, in dit geval een verzameling van \term{karakter}-reeksen. Dergelijke vectoren zijn cruciaal voor het gebruik en begrijpen van \term{R}, waarmee we op het tweede komen. Het handige van een \term{vector} is namelijke dat de elementen die de reeks (\term{vector}) vormen vervangen kunnen worden. Deze bewerkingmogelijkheid zullen we gaan gebruiken om de variabele namen van ons dataframe te gaan veranderen.
Voordat we echter deze mogelijkheid gaan bekijken maken we eerst een ''kopie'' van het \term{diamanten}-dataframe zodat we niet het orgineel gaan aanpassen.\footnote{Nu is het natuurlijk een kleine moeite om het dataframe opnieuw in te lezen, echter voor de overzichteloijkheid is hier niet voor gekozen}:
<<label="DiamantenNewName", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten_kopie <- diamanten
# Check of dataframes inderdaad gelijk zijn
identical(x=diamanten_kopie, y=diamanten)
@
Zoals je ziet laat de functie \func{identical} zien dat we nu twee identieke dataframes hebben, waarvan we het kopie gaan bewerken. Stel nu dat we bijvoorbeeld de variabelen V1 t/m V10 willen noemen, dan kan dit als volgt:
<<label="DiamantenNewVariableName", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
colnames(x=diamanten_kopie) <- c("V1","V2","V3","V4","V5",
"V6","V7","V8","V9","V10")
# Controleren
head(x=diamanten_kopie, n=2)
@
Zoals je ziet hebben de variabelen de gewenste nieuwe namen gekregen. Maar wat gebeurd er nu precies? In Figuur \ref{fig:schemaToewijzing} is dit schematisch weergegeven. De nieuwe namen zijn ten eerste ook ondergebracht in een \term{vector}. De \texttt{c} staat namelijk voor samenvoegen van waardes/elementen, en heeft een \term{vector} als resultaat. In dit geval zijn dus de \term{karakter}-reeksen \texttt{''V1''} t/m \texttt{''V10''} samengevoegd in een \term{vector}.
Er staat dus zowel aan de linkse als de rechts kant van de \texttt{<-} een \term{vector}. Waarbij aan de linkse kant de \term{vector} bestaat uit de oorspronkelijke namen, terwijl aan de rechtse kan de \term{vector} staat met de nieuwe namen, Bij de eerste stap van de bewerking wordt er gekeken naar het eerste element van de \term{vector} aan de linkse kant (de oorspronkelijke namen). In dit geval is dit de \term{karakter}-reeks met als waarde \texttt{''carat''}. Vervolgens wordt deze waarde vervangen door het eerste element van de vector aan de rechtse kant (de nieuwe namen), in dit geval \texttt{''V1''}. Deze cyclus begint hierna weer van voor af aan. Het tweede \term{element} in oorspronkelijke \term{vector} wordt dus gezocht (\texttt{''clarity''}) en vervangen met het tweede \term{element} uit de nieuwe \term{vector}. Dit proces herhaald zich net zo lang tot de alle posities van de oorspronkelijke \term{vector} zijn afgegaan. De laatste bewerking behelst dus de hercodering van \texttt{''z''} met \texttt{''V10''}.
% Define block styles http://www.texample.net/tikz/examples/simple-flow-chart/
\tikzstyle{block} = [rectangle, draw=textblue, fill=textblue!20,
text centered,line width=1pt, minimum height=2em, minimum width=3em,line width=2pt]
\tikzstyle{line} = [draw, -latex',line width=1pt]
%Picture
\begin{figure}[!h]
\begin{figframe}
\centering
\begin{tikzpicture}[scale=2, font=\sffamily]
% Old variables names
\draw[gray, fill=gray!20] (-.5,.3) rectangle (4,-.3);
\node[rotate=90,anchor=south, align=center] (oldL) at (-.5,0) {Oude\\ namen};
\node[block,align=center] (old1) at (0, 0) {carat};
\node[block,align=center] (old2) at (1, 0) {cut};
\node[block,align=center] (old3) at (2, 0) {clarity};
\node[block,align=center] (old4) at (3.5, 0) {z};
\node[align=center] (oldp) at ($ (old3.east) !.5! (old4.west) $) {\ldots};
% New variables names
\draw[gray, fill=gray!20] (-.5,-.7) rectangle (4,-1.3);
\node[rotate=90,anchor=south, align=center] (newL) at (-.5,-1) {Nieuwe\\ namen};
\node[block,align=center] (new1) at (0, -1) {V1};
\node[block,align=center] (new2) at (1, -1) {V2};
\node[block,align=center] (new3) at (2, -1) {V3};
\node[block,align=center] (new4) at (3.5, -1) {V10};
\node[align=center] (newp) at ($ (new3.east) !.5! (new4.west) $) {\ldots};
%
\path [line] (new1) -- (old1);
\path [line] (new2) -- (old2);
\path [line] (new3) -- (old3);
\path [line] (new4) -- (old4);
\end{tikzpicture}
\caption{Toewijzing van nieuwe variabele namen ter vervanging van de oorsprongelijke, oude, namen. Zoals te zien wordt de eerste nieuwe naam toegewezen aan de eerste oude naam, de tweede nieuwe aan de twee oude, etc.} \label{fig:schemaToewijzing}
\end{figframe}
\end{figure}
In dit voorbeeld hebben we dus alle variabelen gelijk benoemd. Stel nu eeens dat we slechts twee variabelen een nieuwe naam willen geven. Dan kunnen we gebruik maken van een bewerking die we in het kookboek bij de selectie van rijen en kolommen terug hebben gezien:
<<label="DiamantenOneNewVariableName", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten_kopie <- diamanten
# Geeft alleen naam van tweede variabele
colnames(x=diamanten_kopie)[c(2,10)]
# Past de naam van de variabele aan
colnames(x=diamanten_kopie)[c(2,10)] <- c("kwaliteit","diepte")
# Controleren
colnames(x=diamanten_kopie)[c(2,10)]
@
Zoals je ziet hebben we \texttt{[c(2,10)]} toegevoegd, wat op zichzelf ook weer een \term{vector} is, waardoor we alleen het tweede en tiende element selecteren van het object dat door de functie \func{colnames} wordt geproduceerd. Dat ging misschien een beetje te snel, dus laten we het even stap voor stap doen. Zoals we hebben gezien produceert de functie \func{colnames} een \term{vector} van variabele namen en is het mogelijk om deze te bewerken. De \keys{[} en \keys{]} zorgen er echter voor dat we een selectie van deze \term{vector} maken. Zoals je ziet bij de tweede lijn van de syntax krijg je ook alleen deze namen te zien (\texttt{''cut''} \& \texttt{''z''}). Vervolgens is het mogelijk om deze elementen te vervangen met nieuwe variabele namen. Dit gebeurd weer d.m.v. de toevoeging van de \texttt{<-} en een vector die de nieuwe waardes bevat, in dit geval \texttt{''kwaliteit''} en \texttt{''diepte''}. De toevoeging \texttt{[c(2,10)]} zorgt eigenlijk voor een soort filter, zoals te zien in Figuur \ref{fig:schemaToewijzingFilter}. Alleen de elementen waarvan de positie overeenkomt met een van de waardes van de filter worden geselecteerd. Het eerste geselecteerde/gefilterde element is dus \texttt{''cut''} wat wordt vervangen door het eerste element van de vector aan de rechtse kant \texttt{''kwaliteit''}. Het tweede element wat door de filter komt is het tiende en laatste element \texttt{''z''} wat wordt vervangen door het tweede element van de rechtse \term{vector}, \texttt{''diepte''}.
In de loop van dit boek zullen nog vele varianten en alternatieve manieren van filteren de revu passeeren. Het doel is echter altijd gelijk; een deel van een object selecteren.
% Define block styles http://www.texample.net/tikz/examples/simple-flow-chart/
%Picture
\begin{figure}[!h]
\begin{figframe}
\centering
\begin{tikzpicture}[scale=2, font=\sffamily]
% Old variables names
\draw[gray, fill=gray!20] (-.5,.3) rectangle (4,-.3);
\node[rotate=90,anchor=south, align=center] (oldL) at (-.5,0) {Oude\\ namen};
\node[block,align=center] (old1) at (0, 0) {carat};
\node[block,align=center] (old2) at (1, 0) {cut};
\node[block,align=center] (old3) at (2, 0) {clarity};
\node[block,align=center] (old4) at (3.5, 0) {z};
\node[align=center] (oldp) at ($ (old3.east) !.5! (old4.west) $) {\ldots};
% Old variables names
\draw[gray, fill=gray!20] (-.5,-.7) rectangle (4,-1.3);
\node[rotate=90,anchor=south, align=center] (oldL) at (-.5,-1) {Filter};
\node[block,align=center] (fil1) at (0, -1) {\xmark};
\node[block,align=center] (fil2) at (1, -1) {\cmark};
\node[block,align=center] (fil3) at (2, -1) {\xmark};
\node[block,align=center] (fil4) at (3.5, -1) {\cmark};
\node[align=center] (fillp) at ($ (fil3.east) !.5! (fil4.west) $) {\ldots};
% New variables names
\draw[gray, fill=gray!20] (-.5,-1.7) rectangle (1.5,-2.3);
\node[rotate=90,anchor=south, align=center] (newL) at (-.5,-2) {Nieuwe\\ namen};
\node[block,align=center] (new1) at (0, -2) {kwaliteit};
\node[block,align=center] (new2) at (1, -2) {diepte};
%
\path [line] (new1.north) -- (fil2.south);
\path [line] (new2.north) -- (fil4.south);
\path [line] (fil2) -- (old2);
\path [line] (fil4) -- (old4);
\path [line, dashed] (fil1) -- (old1);
\path [line, dashed] (fil3) -- (old3);
\end{tikzpicture}
\caption{Schematische weergave van toewijzing van nieuwe variabele namen aan een selectie van de oorspronkelijke namen. Doordat alleen de tweede en tiende variabele namen zijn geselecteerd wordt de eerste nieuwe naam toegewezen aan de twee oude naam, en de tweede nieuwe naam aan de tiende oude naam. Iedere nieuwe waarde wordt dus bij de eerst mogelijke positie van de oorspronkelijke vector gekoppeld.} \label{fig:schemaToewijzingFilter}
\end{figframe}
\end{figure}
\subsection{Object manipulatie}
De bvoenstaand filter-technieken worden in principe ook toegepast bij het selecteren van rijen en kolommen van dataframes. Als voorbeeld kunnen we de code nemen zoals in het kookboek workt gebruikt; \texttt{diamanten[,c(''carat'')]}. Omdat een dataframe twee dimensies heeft is het van belang om aan te geven over welke dimensie je de filter wilt toepassen, de rijen of de kolommen.\footnote{Dit dus in tegenstelling tot het filteren van een \term{vector}, welke slechts \'e\'en dimensie heeft.} Om aan te geven welke dimensie we willen filteren gebruiken we de \keys{,}, waarbij alle invoer voor de \keys{,} wordt gebruikt om de rijen te filteren, en alle informatie na de \keys{,} voor de kolommen. Als er voor een dimensie geen invoer wordt gegeven wordt deze hele dimensie behouden, er wordt dan dus niet gefilterd.
In het voorbeeld (\texttt{diamanten[,c(''carat'')]}) wordt er dus informatie gegeven met betrekking tot de kolommen. Waarbij dus alleen de kolom wordt behouden met de naam \texttt{''carat''}. Het gebruiken van namen om te filteren is mogelijk omdat een dataframe niet alleen nummers aan kolommen toekent maar ook namen. In dit geval heeft de volgende bewerking dus hetzelfde effect.
<<label="BrackDiamantenNumber", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=20)
diamanten[,2]
@
In principe is dit ook wat \term{R} daadwerkelijk doet. Het kijkt welke positie de genoemde variabele in het dataframe heeft, en selecteerd de overeenkomstige kolom. In Figuur \ref{fig:schemaFilterFrame} is te schematisch weergegeven hoe de zojuist beschreven filter werkt.
% Define block styles http://www.texample.net/tikz/examples/simple-flow-chart/
\tikzstyle{block} = [rectangle, draw=black, fill=textblue!20,
text centered,line width=1pt, minimum height=2em, minimum width=2em]
\tikzstyle{fblock} = [rectangle, draw=black, fill=textblue!10,
text centered,line width=1pt, minimum height=2em, minimum width=2em,text=black!50,draw=black!50]
\tikzstyle{line} = [draw, -latex']
%Picture
\begin{figure}[!h]
\begin{figframe}
\centering
\begin{tikzpicture}[scale=2]
% Old variables names
\node[block,align=center] (X11) at (0, 0) {$X_{1,1}$};
\node[block,align=center] (X12) at (.5, 0) {$X_{1,2}$};
\node[block,align=center] (X13) at (1, 0) {$X_{1,3}$};
\node[block,align=center] (X1j) at (1.75, 0) {$X_{1,j}$};
\node[align=center] (X1jdot) at ($ (X13.east) !.5! (X1j.west) $) {\ldots};
\node[block,align=center] (X21) at (0, -.5) {$X_{2,1}$};
\node[block,align=center] (X22) at (.5, -.5) {$X_{2,2}$};
\node[block,align=center] (X23) at (1, -.5) {$X_{2,3}$};
\node[block,align=center] (X2j) at (1.75, -.5) {$X_{2,j}$};
\node[align=center] (X2jdot) at ($ (X23.east) !.5! (X2j.west) $) {\ldots};
\node[block,align=center] (X31) at (0, -1) {$X_{3,1}$};
\node[block,align=center] (X32) at (.5, -1) {$X_{3,2}$};
\node[block,align=center] (X33) at (1, -1) {$X_{3,3}$};
\node[block,align=center] (X3j) at (1.75, -1) {$X_{3,j}$};
\node[align=center] (X3jdot) at ($ (X33.east) !.5! (X3j.west) $) {\ldots};
\node[block,align=center] (Xi1) at (0, -1.75) {$X_{i,1}$};
\node[block,align=center] (Xi2) at (.5, -1.75) {$X_{i,2}$};
\node[block,align=center] (Xi3) at (1, -1.75) {$X_{i,3}$};
\node[block,align=center] (Xij) at (1.75, -1.75) {$X_{i,j}$};
\node[align=center] (Xijdot) at ($ (Xi3.east) !.5! (Xij.west) $) {\ldots};
\node[align=center, rotate =90] (Vdot1) at ($ (Xi1.north) !.5! (X31.south) $) {\ldots};
\node[align=center, rotate =90] (Vdot2) at ($ (Xi2.north) !.5! (X32.south) $) {\ldots};
\node[align=center, rotate =90] (Vdot3) at ($ (Xi3.north) !.5! (X33.south) $) {\ldots};
\node[align=center, rotate =90] (Vdot4) at ($ (Xij.north) !.5! (X3j.south) $) {\ldots};
% Old variables names
\node[fblock,align=center] (aX11) at (2.75, 0) {$X_{1,1}$};
\node[block,align=center] (aX12) at (3.25, 0) {$X_{1,2}$};
\node[fblock,align=center] (aX13) at (3.75, 0) {$X_{1,3}$};
\node[fblock,align=center] (aX1j) at (4.5, 0) {$X_{1,j}$};
\node[align=center] (aX1jdot) at ($ (aX13.east) !.5! (aX1j.west) $) {\ldots};
\node[fblock,align=center] (aX21) at (2.75, -.5) {$X_{2,1}$};
\node[block,align=center] (aX22) at (3.25, -.5) {$X_{2,2}$};
\node[fblock,align=center] (aX23) at (3.75, -.5) {$X_{2,3}$};
\node[fblock,align=center] (aX2j) at (4.5, -.5) {$X_{2,j}$};
\node[align=center] (aX2jdot) at ($ (aX23.east) !.5! (aX2j.west) $) {\ldots};
\node[fblock,align=center] (aX31) at (2.75, -1) {$X_{3,1}$};
\node[block,align=center] (aX32) at (3.25, -1) {$X_{3,2}$};
\node[fblock,align=center] (aX33) at (3.75, -1) {$X_{3,3}$};
\node[fblock,align=center] (aX3j) at (4.5, -1) {$X_{3,j}$};
\node[align=center] (aX3jdot) at ($ (aX33.east) !.5! (aX3j.west) $) {\ldots};
\node[fblock,align=center] (aXi1) at (2.75, -1.75) {$X_{i,1}$};
\node[block,align=center] (aXi2) at (3.25, -1.75) {$X_{i,2}$};
\node[fblock,align=center] (aXi3) at (3.75, -1.75) {$X_{i,3}$};
\node[fblock,align=center] (aXij) at (4.5, -1.75) {$X_{i,j}$};
\node[align=center] (aXijdot) at ($ (aXi3.east) !.5! (aXij.west) $) {\ldots};
\node[align=center, rotate =90] (aVdot1) at ($ (aXi1.north) !.5! (aX31.south) $) {\ldots};
\node[align=center, rotate =90] (aVdot2) at ($ (aXi2.north) !.5! (aX32.south) $) {\ldots};
\node[align=center, rotate =90] (aVdot3) at ($ (aXi3.north) !.5! (aX33.south) $) {\ldots};
\node[align=center, rotate =90] (aVdot4) at ($ (aXij.north) !.5! (aX3j.south) $) {\ldots};
%line
\draw[line width=1pt, dashed] (2.25,.25) -- node [anchor=center, fill=white,align=center,rotate=90] {Filter = [,2]} (2.25,-2) ;
\end{tikzpicture}
\caption{Schematische weergave van de werking van een filter bij een dataframe. De filter is in dit geval, \texttt{[,2]}. Hierdoor wordt dus alleen de tweede kolom geselecteerd. Omdat er geen informatie is toegewezen voor de \keys{,} worden alle rijen geselecteerd.} \label{fig:schemaFilterFrame}
\end{figframe}
\end{figure}
Als er slechts een kolom hoeft te worden gefilterd is het niet nodig om de variabele-naam of kolom-nummer tussen \keys{(+)} te plaatsen. Dus \texttt{diamanten[\allowbreak,c(''carat'')]} staat gelijk aan \texttt{diamanten[,\allowbreak''carat'']}. Echter als er meerde variabelen worden geselecteerd is dit wel nodig. Als er immers geens \keys{(+)} worden gebruikt dan is het voor \term{R} niet duidelijk welke invoer waarvoor bestemd is. Als we bijvoorbeeld naar het tweede voorbeeld kijken uit het kookboek, \texttt{diamanten[,c("carat","color")]}, dan zou het fout gaan als we de variabele-namen niet in een vector zouden plaatsen:
<<label="BrackDiamantenMultipleFout", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=20)
diamanten[,"carat","color"]
@
Zoals je ziet krijg je een error. Dit komt omdat je voor teveel dimensies informatie geeft. Daarom is het dus van belang om de filters voor de rijen respectievelijk de kolommen in een \term{vector} te plaatsen. Waarbij de \term{vector} voor de \keys{,} dus de filter aangeeft voor de rijen en de \term{vector} na de \keys{,} voor de kolommen. Maar hoe zit het dan met het de \keys{:} zoals in bijvoorbeeld \texttt{diamanten[1:5,]
}~? De bewerking is mogelijk omdat het gebruik van een \keys{:} resulteert in een \term{vector}:
<<label="Vector1to5", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
1:5
# Is gelijk aan
c(1,2,3,4,5)
@
En aangezien een \term{vector} gebruikt kan worden als vector is het mogelijk om op deze manier de eerste tot en met de vijfde rij te selecteren.
Het gaat er dus om dat er de invoer na en voor de \keys{,} een \term{vector} is die gebruikt kan worden als een filter. Hierbij is het bijvoorbeeld niet van belang wat de volgorde is van de filter.
<<label="BrackDiamantenOrder", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=20)
diamanten[,c("color","carat")]
@
Zoals je ziet worden nog steeds dezelfde variabelen gefiltert. Echter, let op! De volgorde van de variabelen in het nieuwe, gefilterde, dataframe is wel veranderd. Het neemt de volgorde aan zoals deze in de filter is gegeven. Tot slot nog een voorbeeld waarin we de 1\textsuperscript{e}, 10\textsuperscript{e}, 100\textsuperscript{e}, en de 1000\textsuperscript{e} rij filteren:
<<label="BrackDiamantenRow110", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=100)
diamanten[c(1,10,100,1000),]
@
Naast het gebruik van variabele namen, kolom- en rijnummers, als filters is echter nog een andere methode. Deze maakt ook gebruik van vectors, alleen ditmaal zijn de elementen geen cijfers of namen maar \term{logisische constanten}.\footnote{Engels = Logical constants} Deze term is misschien nieuw, de elementen niet. Dit gaat namelijk om de elementen \texttt{TRUE} en \texttt{FALSE} welke ook al zijn behandeld in relatie tot het gebruik van functies. Hierbij werd aangegeven dat deze toestemming geven (of niet) aan het uitvoeren van bepaalde elementen in een functie. De werking van deze \term{logisische constanten} bij het filteren van een dataframe is in principe hetzelfde:
<<label="BrackDiamantenLogical", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=20)
diamanten[,c(FALSE,TRUE,FALSE,FALSE,FALSE,
TRUE,FALSE,FALSE,FALSE,FALSE)]
@
Zoals je ziet worden nu de alleen de tweede en zesde kolom geselecteerd. Het lastige van deze methode is echter dat je voor iedere kolom moet aangeven of deze al dan niet gefilterd moet worden. In dit geval is nog te overzien maar stel nu dat al we rij 1 t/m 10 willen selecteren. Dan zouden we een vector van \term{logisische constanten} nodig hebben met \Sexpr{nrow(diamanten)} elementen. Dit is natuurlijk absurd, en op deze manier heeft deze manier van filteren ook weinig zin. Het heeft echter wel nut als we rijen willen selecteren die aan een bepaalde voorwaarde voldoen. Stel nu eens dat we alleen maar de rijen willen met diamanten die als kleur \texttt{''E''} hebben. Dan kan dat als volgt:
<<label="BrackDiamantenLogicalRow", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=100)
diamanten[diamanten$color=="I",]
@
Dit gaat misschien een beetje snel, dus daarom gaan we even stap voor stap bekijken wat hier nu precies gebeurd. Eerst kunnen we vaststellen dat we rijen gaan filteren omdat we informatie invoeren voor de \keys{,}. De kolommen laten we onaangetast aangezien we na de \keys{,} geen informatie invoeren. Daarna gaan we kijken wat we precies voor een vector invoeren:
<<label="BrackDiamantenLogicalRowBreak1", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten$color=="I"
@
Voor het \texttt{==}-teken staat een vector, namelijk de \texttt{color}-kolom van het dataframe. Dit is dus een \term{vector} met een lengte van \Sexpr{nrow(diamanten)} waarin de waardes voor iedere rij op de variabele \texttt{color} zijn gegeven:
<<label="BrackDiamantenLogicalRowBreak1a", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
diamanten$color
@
Het \texttt{==}-teken bekijkt of de elementen voor het teken gelijk zijn aan de elementen (in dit geval \'e\'en element) na het teken. In dit geval wordt dus voor alle \Sexpr{nrow(diamanten)} waardes gekeken of deze gelijk is aan \texttt{''I''}. Zoals we kunnen zien zijn de eerste drie waardes niet gelijk aan \texttt{''I''}, de uitkomst is immers \texttt{FALSE}. De vierde waarde is echter wel gelijk aan \texttt{''I''}. Deze informatie wordt samengevoegd in een \term{vector} waarin er dus voor iedere rij controleerd of de kleur van de diamant gelijk is aan een door ons gespecifeerde kleur. Deze \term{vector} kan dan dus dienst doen als filter aangezien het voor iedere rij specifieerd of deze rij in het dataframe moet blijven, of niet.
Aangezien deze methode nogal lastig is (zeker als er meerdere filters moeten worden toegepast), is er ook de \func{subset}-functie.\footnote{Het ongelukkige aan deze functie vind ik zelf dat zowel een element als de functie zelf de naam \emph{subset} hebben. Dit kan soms verwarrend werken.} Deze functie is al kort toegelicht in het kookboek (\texttt{subset(x=diamanten,\allowbreak subset=cut==''Very Good'')}). De werking van deze functie is ook gebasseerd op \term{logisische constanten}, alleen de notatie is wat overzichtelijker. De zojuist gebruikte filter, \texttt{diamanten\allowbreak [diamanten\$color==\allowbreak ''I'',]}, kan namelijk eenvoudig als volgt worden genoteerd:
<<label="BrackDiamantenSubsetEqual", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
subset(x=diamanten, subset=color=="I")
@
Dit resulteert in precies hetzelfde dataframe, het is maar net waar je voorkeur ligt! De \func{subset}-functie heeft als voordeel dat waneer er meerdere filters moeten worden teogepast het nog steeds redelijk overzichtelijk blijft.
<<label="BrackDiamantenSubsetMultiple", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
# Zowel kleur "I" als kwaliteit "Premium"
subset(x=diamanten, subset= color=="I" & cut=="Premium")
# OF kleur "I" OF kwaliteit "Premium" (of "toevallig" beide)
subset(x=diamanten, subset= color=="I" | cut=="Premium")
@
Hierbij defineert een \keys{\&} \emph{zowel}, en een \keys{\textbar} \emph{of}. Het kan natuurlijk zo complex als je maar wilt, dit gaat echter het doel van dit boek te buiten. Een goed advies is altijd om complexere filters in meerdere stappen uit tevoeren, om op deze manier het overzicht te bewaren.
\begin{tip}[Waarom \term{R} geweldig is]
In het begin kan het cre\"eeren van bepaalde subsets van je data erg lastig zijn, als je het echter onder de knie krijgt zal je merken dat \term{R} eindeloze mogelijkheden biedt. Stel bijvoorbeeld dat we maar diamanten willen selecter die een een karaat-gehalte boven het gemiddelde hebben. Dan zouden we eerst kunnen kijken naar het gemiddelde, om dit vervolgens in de filter te gebruiken:
<<label="RisGreat", tidy=FALSE, highlight=TRUE, warning=FALSE, echo=-1>>=
options(max.print=20)
mean(diamanten$carat, na.rm=TRUE)
subset(x=diamanten, subset= carat>0.7979397)
@
Stel nu echter dat de dataset veranderd, omdat er bijvoorbeeld nieuwe data beschikbaar. In dit geval zouden we opnieuw het gemiddelde moeten uitrekenen en het oude gemiddelde hiermee vervangen. Het kan echter eenvoudiger:
<<label="RisGreat2", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
subset(x=diamanten,
subset= carat>mean(diamanten$carat, na.rm=TRUE))
@
Het gemiddelde wordt dus eerste berekend en vervolgens gebruikt als waarde waartegen het karaat-gehalte van iedere diamant tegen wordt afgezet. Vergelijking die wordt gemaakt is dus niet langer statisch, maar dynamisch geworden. Als het gemiddelde door wat voor een reden veranderd, zal het filter namelijk nog steeds dezelfde werking hebben!
\end{tip}
\subsection{Beschrijvende statistiek}
Een laatste kijkje in de keuken in de hoofdstuk betreft de beschrijvende statistiek. De \func{summary}-functie spreekt voor zich, evenals de functies die nodig zijn om de verschillende spreidings- en centrummaten te verkrijgen. Wel is het misschien goed om even stil te staan bij de tabellen. Ten eerste is belangrijk om te begrijpen wat er bij de laatste tabel gebeurde:
<<label="KarakterMogelijkhedenAdvanced", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
prop.table(table(diamanten$cut))*100 #als percentage
@
Lijkt logisch, en dat is het ook. Toch is het goed om te begrijpen wat er precies gebeurd. Eerst wordt er door \term{R} een object geproduceert. In dit geval bestaat dit uit aantallen. Daarna worden deze aantallen omgezet in proporties. Belangrijker is echter dat het dergelijke object, met de proporties of ruwe aantallen, alleen numerieke waardes bevat. Daarom wordt het mogelijk om allerlei, mathematische, bewerkingen uit te voeren op deze waardes.
Een andere optie van tabellen die in het kookboek niet zijn genoemd, zijn kruistabellen. Dit is relatief eenvoudig:
<<label="Kruistabel", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
table(diamanten$cut,diamanten$color)
@
Ook hierbij is natuurlijk mogelijk om, op een gelijke manier als bij de univariate-tabel, percentages en proporties weer te geven:
<<label="KruistabelPer", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
# Percentages
prop.table(table(diamanten$cut,
diamanten$color)
)*100
@
\begin{tip}[Het afbreken van lijnen]
Zoals je al af en toe hebt gezien wordt niet altijd alle invoer op een lijn geplaatst. Dit heeft voor dit boek het voordeel dat alles netjes binnen de lijntjes blijft, maar heeft ook het algemene voordeel dat de syntax leesbaar blijft. Daar waar we momenteel nog maar korte stukjes syntax hebben, zal dit namelijk snel meer worden. Zeker als er meerdere \keys{()}, \keys{,}, en/of \keys{'} worden gebruikt wordt het soms onduidelijk door welk \keys{)} een \keys{(} wordt gesloten. Voor \term{R} maakt het niet uit over hoeveel lijnen je de code verdeeld. Zolang er namelijk nog sluitende \keys{)} of \keys{'} ontbreken zal het de de invoer niet onderbreken:
<<label="Fout", tidy=FALSE, highlight=TRUE, eval=FALSE, warning=FALSE>>=
prop.table(table(diamanten$cut,
diamanten$color)
@
Zoals je ziet komt er in de \texttt{console} een \keys{+} te staan. Dit komt omdat \term{R} nog extra informatie verwacht aangezien de \term{functie} nog niet ''afgesloten'' is. Als je nu in de \texttt{console} klikt en heel veel \keys{enter} geeft zal je merken dat er nog niks veranderd. Om de \term{functie} toch ''af te sluiten'', kunnen we het ontbrekende \keys{)} geven:\footnote{Het is ook altijd mogelijk om op \keys{Esc} te duwen. Dan worden alle bewerkingen gestopt en komt er weer een nieuwe, lege, regel te staan!.}
<<label="FoutK", tidy=FALSE, highlight=TRUE, eval=FALSE, warning=FALSE>>=
)
*100
@
Maar waarom krijg je nu een error? Dat komt omdat het stukje \texttt{*100} een geheel nieuwe invoer lijn is. Hier begin \term{R} dus opnieuw te werken. En aangezien \texttt{*100} een bewerking is die over een \term{object} moet worden uitgevoerd, is dit niet mogelijk aangezien deze niet gegeven is. Het ''ongestraft'' afbreken van syntax kan dus alleen als de \term{functie} of bewerking nog niet afgesloten is, zodra dit wel is gebeurd zal \term{R} weer ''opnieuw'' beginnen. Onderstaande had wel gewerkt:
<<label="FoutK2", tidy=FALSE, highlight=TRUE, eval=FALSE, warning=FALSE>>=
)*100
@
\end{tip}
Tot slot blikken we nog even terug op het gebruik van correlaties in \term{R}. Zoals werd gedemonstreerd in het kookboek kunnen correlaties eenvoudig worden berekend door de \term{functie} \texttt{cor()} te gebruiken. Er is echter een grote tekortkoming aan deze basis-\term{functie}, het geeft namelijk geen significantie-niveau's (\emph{p}-waardes) voor de correlaties. Om significantie-niveau's te verkrijgen is het daarom nodig om een pakket te installeren dat dit wel kan, het \term{Hmisc}-pakket. Om dit pakket te installeren kunnen dezelfde stappen worden doorlopen als bij het installeren van het \term{foreign}-pakket (blz. \pageref{sec:DataKookForeign}), dus bijvoorbeeld:
<<label="InstallSyntaxHmisc", tidy=FALSE, highlight=TRUE, warning=FALSE, eval=FALSE>>=
install.packages("Hmisc")
@
Daarna moeten we dit pakket natuurlijk ook nog activeren:
<<label="RequireSyntaxHmisc", tidy=FALSE, highlight=TRUE, warning=FALSE>>=
require(Hmisc)
@
Vervolgens kunnen we de correlatie van het kookboek opnieuwe berekenen met de correlatie-\term{functie} \func{rcorr} uit het \term{Hmisc}-pakket:
<<label="CorrelatieDiamantenRcorr", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
rcorr(x=diamanten[ ,c("depth","table","price")])
@
Een fout-melding! Hoe kan dit? Zoals als vermeld is de eerste stap als er iets geks gebeurd met een \term{functie} het help-bestand te openen van de \term{functie} in kwestie; \texttt{?rcorr}. Hier staat onder \emph{Arguments} wat er moet worden ingevoerd voor \texttt[black]{x}:
\begin{quotation} \small \noindent a numeric \textbf{matrix} with at least 5 rows and at least 2 columns (if y is absent). For print, x is an object produced by rcorr.\end{quotation}
Het gaat hier vooral om het vet-gedrukte woord, \term{matrix}. De \emph{invoer} voor het element \texttt[black]{x} moet dus uit een \term{matrix} bestaan. Laten we eens kijken of we aan deze eis voldoen, door te vragen of het ingevoerde \term{object} een \term{matrix} is:
<<label="classdataframe", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
is.matrix(x=diamanten[ ,c("depth","table","price")])
# wat is het dan wel?
class(x=diamanten[ ,c("depth","table","price")])
@
Nee dus, het ingevoerde object is een \term{data.frame}. Maar wat is een \term{matrix}, en wat is het verschil met een \term{data.frame}. In principe zijn beide objecten gelijk, daar waar ze allebij uit rijen en kolommen bestaan. Een \term{data.frame} biedt alleen meer opties dan een \term{matrix}. Zo hebben in een \term{matrix} alle waardes dezelfde structruur, dus bijvoorbeeld of allemaal \term{karakter} of allemaal \term{numeriek}. Een ander verschil is dat een \term{matrix} rijen niet behandeld als variabelen, waardoor de mogelijkheden wat beperkter zijn. Er zijn nog meer verschillen maar de kern is dat een \term{matrix} meer moet worden als een mathematisch \term{object} waarmee gerekend kan worden. Het voordeel hiervan is dat een \term{matrix} minder 'meta-informatie' bevat dan een \term{data.frame} waardoor het minder ruimte in beslag neemt. Hierdoor kunnen berekenen sneller worden uitgevoerd.
Na deze korte, en waarschijnlijke te beknopte, toelichting op een \term{matrix} is de kernvraag natuurlijk: Hoe maken we een \term{matrix}? Het is mogelijk om een matrix zelf in te voeren (net zoals het mogelijk is om zelf een \term{data.frame} samen te stellen), maar het is makkelijker om een \term{data.frame} om te zetten in een \term{matrix}. Voordat we dit echter explecitiet gaan toepassen voor de \term{functie} \texttt{rcorr} gaan we eerst even in zijn algemeenheid naar deze omzetting kijken. Om een \term{data.frame} om te zetten naar een \term{matrix} kan de \term{functie} \texttt{as.matrix} gebruikt worden. Zo kunnen we bijvoorbeeld een subset van het \term{diamanten}-\term{data.frame} omzetten naar een \term{matrix} op de volgende manier:
<<label="asmatrixchar", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
as.matrix(x=diamanten[ ,c("depth","table","cut")])
@
Zoals je ziet worden nu dus alle waardes allemaal als een \term{karakter} gezien--dit kan je zien aan de \keys{''} om alle waardes. Dus ook de numerieke waardes van de eerste twee variabelen zijn geconverteerd naar een \term{karakter}. Als er echter alleen variabelen die \term{numeriek} zijn worden geconverteerd zullen de waardes van de uiteindelijke \term{matrix} dit ook zijn:
<<label="asmatrix", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
as.matrix(x=diamanten[ ,c("depth","table","price")])
@
Dit is dus een numerieke \term{matrix}, het soort object wat we dus nodig hebben voor de \term{functie} \texttt{rcorr}. Voor de overzichtelijkheid wijzen we de matrix eerst toe aan een \term{object} om dit vervolgens in de \term{functie} in te voegen:
<<label="CorrelatieDiamantenRcorrmatrix", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
data_cor <- as.matrix(x=diamanten[ ,c("depth","table","price")])
rcorr(x=data_cor)
@
Kijk dat lijkt er al meer op, de correlaties, het aantal rijen (cases) waarover deze berekend zijn, plus het significantie-niveau van iedere correlatieco\"effici\"ent. Tot slot kijken we nog even naar een handig aspect van de uitvoer van deze \term{functie}. Een handigheid die het deelt met veel andere functies. Het is namelijk mogelijk om de uitvoer aan een \term{object} toe te wijzen:
<<label="CorrelatieObject", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
cor_tabel <- rcorr(x=data_cor)
cor_tabel
@
Is dat nu zo baanbrekend? Nee dat niet, maar de mogelijkheden die dit \term{object} met zich mee brengt zijn dat wel. Zo kunnen we apart de significantie-niveau's opvragen:
<<label="CorrelatieObjectPval", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
cor_tabel$P
# p-waarde voor correlatie depth met price
cor_tabel$P["depth","price"]
@
Het tweede voorbeeld is mogelijk doordat de uitvoer van \texttt{cor\_tabel\$P} een object is in de vorm van een \term{matrix}. Hiervan wordt vervolgens de rij geselecteerd met de naam \texttt{depth} en de kolom met de naam \texttt{price}. Hierdoor krijg je dus de \emph{p}-waarde die behoord bij de correlatie tussen deze twee variabelen. De werking is hier dus gelijk als bij de selectie van rijen en kolommen bij een \term{data.frame}.
Daarnaast verdient de werking van het \texttt{\$P} stukje ook nog wat verdere uitleg. Eerder hebben we immers gezien dat \keys{\$} een soort filter is die helpt bij het selecteren van variabelen, terwijl hier een \term{matrix} wordt geselecteerd. Om dit te begrijpen moeten we eerste naar de inhoud van \term{object} \texttt{cor\_tabel} kijken:
<<label="CorrelatieClass", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
str(cor_tabel)
@
Zoals aangegeven betreft het \term{object} een \term{lijst}, met drie verschillende matrices, genaamd \emph{r}, \emph{n}, en \emph{P}.\footnote{\emph{n} is ook een \term{matrix} maar aangezien alle elementen dezelfde waarde bevatten wordt in dit geval slechts een keer deze waarde gegeven (dit is geen algemeenheid en is een speciefieke werking van de \func{rcorr} functie). Zo zijn er wel meer kleine weergave verschillen tussen de aparte weergave van iedere \term{matrix} of de, mooi opgemaakte, totale weergave.} Als we het gehele \term{object} opvragen wordt dus de gehele inhoud van de \term{lijst} gegeven, daar waar we met \keys{\$} een selectie kunnen maken. Dit is ook te zien in de zojusit gegeven output, aangezien er ook een \keys{\$} vermeld staat voor de naam van iedere \term{matrix}. Een andere manier om een gedeelte van een lijst te selecteren is als volgt:
<<label="werkinglijst", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
cor_tabel[[1]]
@
In plaats van enkele \keys{[+]} zijn er bij de selectie vanuit een \term{lijst} dubbele \keys{[+]} nodig.\footnote{Het is ook mogelijk om enkele \keys{[+]} te gebruiken, maar de functionaliteit hiervan gaat te ver voor dit boek.} In dit geval selecteren we dus de eerste index uit de \term{lijst} in dit geval \emph{r}, de correlatieco\"effici\"enten. In feite lijkt de werking dus heel erg op de selectie van variabelen uit een \term{data.frame}, alleen ditmaal een dimensie hoger. Een \keys{\$} selecteerd dus een sub-onderdeel van een bepaald object, zoals is ge\"ilustreerd in Figuur \ref{fig:schemaLijstFilter}. Tot slot is het belangrijk om te begrijpen dat een \term{lijst} uit verschillende soorten objecten kan worden opgebouwd. Het hoeft dus niet uit alleen maar dataframes of vectoren te bevatten:
<<label="werkinglijstdif", tidy=FALSE, highlight=TRUE, warning=TRUE>>=
voorbeeld_lijst <- list(A=data.frame(V1=1:10,V2=11:20),
B=matrix(c(1:20),ncol=2),
C=1:20,
D=LETTERS[1:20])
str(voorbeeld_lijst)
@
\begin{figure}[!h]
\begin{figframe}
\centering
\begin{tikzpicture}[scale=2, font=\sffamily]
\node[block,align=center] (Overal) at (2.45, 1.5) {Cor\_tabel};
% Correlation
\fill [gray!30, label=Nbox] (-.5,.5) rectangle (1.4,-1.4);
\node[text= black!60,anchor=south, text height=1.5ex, text depth=.1ex] (rlab) at (.45,.5) {r};
\node[fblock,align=center] (X11) at (0, 0) {$r_{1,1}$};
\node[fblock,align=center] (X12) at (.5, 0) {$r_{1,2}$};
\node[fblock,align=center] (X13) at (1, 0) {$r_{1,3}$};
\node[fblock,align=center] (X21) at (0, -.5) {$r_{2,1}$};
\node[fblock,align=center] (X22) at (.5, -.5) {$r_{2,2}$};
\node[fblock,align=center] (X23) at (1, -.5) {$r_{2,3}$};
\node[fblock,align=center] (X31) at (0, -1) {$r_{3,1}$};
\node[fblock,align=center] (X32) at (.5, -1) {$r_{3,2}$};
\node[fblock,align=center] (X33) at (1, -1) {$r_{3,3}$};
\node[text= black!80, anchor=south, text height=1.5ex, text depth=.1ex] at (X11.north) {depth};
\node[text= black!80, anchor=south, text height=1.5ex, text depth=.1ex] at (X12.north) {table};
\node[text= black!80, anchor=south, text height=1.5ex, text depth=.1ex] at (X13.north) {price};
\node[text= black!80, rotate=90, anchor=south, text height=1.5ex, text depth=.1ex] at (X11.west) {depth};
\node[text= black!80, rotate=90, anchor=south, text height=1.5ex, text depth=.1ex] at (X21.west) {table};
\node[text= black!80, rotate=90, anchor=south, text height=1.5ex, text depth=.1ex] at (X31.west) {price};
% N