Daten importieren: Teil 1
RStudio Projekt
In der heutigen Sitzung werden wir Datensätze eines mit Psychopy erstellten Verhaltensexperimentes in R importieren. Die Datensätze stammen aus dem Kurs im FS 2022. Sie können unter folgendem Link ein RStudio Projekt herunterladen. Dieses muss zuerst “entzippt” werden. In dem Projektordner finden Sie zwei Ordner; In testdata
befindet sich ein einzelner Datensatz, und in data
befinden sich neun Datensätze. Das Projekt kann durch einen Doppelklick auf das File import-data.Rproj
geöffnet werden.
Erstellen Sie zuerst ein R Script
. In dieses File kommt der R Code, den wir benutzen, um die Files zu importieren. Sie können den Code aus den mit grauem Hintergrund gekennzeichneten Code Chunks kopieren. Wir werden zuerst den einzelnen Datensatz einlesen, und bearbeiten. Danach werden wir lernen, wie wir diese Schritte automatisch auf mehrere Datensätze anwenden.
Einen Datensatz bearbeiten
Wir benötogen für alle nachfolgenden Schritte zuerst das tidyverse
Package.
CSV File importieren
Wir werden nun das File ZZ_rdk-discrimination_2022_Mar_07_1403.csv
aus dem testdata
Ordner einlesen. Bevor wir das tun, ist es sinnvoll, sich das File z.B. in Excel anschauen.
Nun können Sie entweder über die GUI-Option (Menu > File > Import Dataset > From text (readr)
) oder direkt das File einlesen.
testdata <- read_csv("testdata/ZZ_rdk-discrimination_2022_Mar_07_1403.csv")
Variablen ĂĽberprĂĽfen
glimpse(testdata)
Rows: 167
Columns: 39
$ cue <chr> "none", "left", "right", "l…
$ direction <chr> "right", "right", "right", …
$ practice_block_loop.thisRepN <dbl> 0, 0, 0, 0, 0, 0, NA, NA, N…
$ practice_block_loop.thisTrialN <dbl> 0, 1, 2, 3, 4, 5, NA, NA, N…
$ practice_block_loop.thisN <dbl> 0, 1, 2, 3, 4, 5, NA, NA, N…
$ practice_block_loop.thisIndex <dbl> 5, 2, 1, 0, 4, 3, NA, NA, N…
$ main_blocks_loop.thisRepN <dbl> NA, NA, NA, NA, NA, NA, NA,…
$ main_blocks_loop.thisTrialN <dbl> NA, NA, NA, NA, NA, NA, NA,…
$ main_blocks_loop.thisN <dbl> NA, NA, NA, NA, NA, NA, NA,…
$ main_blocks_loop.thisIndex <dbl> NA, NA, NA, NA, NA, NA, NA,…
$ static_isi.started <dbl> 0.01033428, 0.03202713, 0.0…
$ static_isi.stopped <dbl> 2.010334, 2.032027, 2.03217…
$ fixation_pre.started <dbl> 26.79425, 36.16522, 44.7852…
$ fixation_pre.stopped <chr> "None", "None", "None", "No…
$ image.started <dbl> 27.19849, 36.28205, 46.0032…
$ image.stopped <chr> "None", "None", "None", "No…
$ fixation_post.started <dbl> 28.17814, 37.28240, 47.0037…
$ fixation_post.stopped <chr> "None", "None", "None", "No…
$ dots_background.started <dbl> 32.18642, 41.30145, 52.0107…
$ dots_background.stopped <chr> "None", "None", "None", "No…
$ dots_stimulus.started <dbl> 32.18642, 41.30145, 52.0107…
$ dots_stimulus.stopped <chr> "None", "None", "None", "No…
$ dots_keyboard_response.keys <chr> "None", "f", "j", "f", "Non…
$ dots_keyboard_response.started <dbl> 32.18642, 41.30145, 52.0107…
$ dots_keyboard_response.stopped <chr> "None", "None", "None", "No…
$ feedback_text.started <dbl> 33.70200, 42.28899, 52.9229…
$ feedback_text.stopped <chr> "None", "None", "None", "No…
$ dots_keyboard_response.rt <dbl> NA, 0.9339199, 0.8488816, 0…
$ instruction_main_text.started <dbl> NA, NA, NA, NA, NA, NA, 81.…
$ instruction_main_text.stopped <chr> NA, NA, NA, NA, NA, NA, "No…
$ instruction_main_keyboard_response.keys <chr> NA, NA, NA, NA, NA, NA, "sp…
$ instruction_main_keyboard_response.rt <dbl> NA, NA, NA, NA, NA, NA, 3.1…
$ instruction_main_keyboard_response.started <dbl> NA, NA, NA, NA, NA, NA, 81.…
$ instruction_main_keyboard_response.stopped <chr> NA, NA, NA, NA, NA, NA, "No…
$ Pseudonym <chr> "ZZ", "ZZ", "ZZ", "ZZ", "ZZ…
$ date <chr> "2022_Mar_07_1403", "2022_M…
$ expName <chr> "rdk-discrimination", "rdk-…
$ psychopyVersion <chr> "03.02.21", "03.02.21", "03…
$ frameRate <dbl> 59.9, 59.9, 59.9, 59.9, 59.…
Practice Trials löschen
Vielleicht haben Sie bemerkt, dass die ersten 6 Zeilen Übungstrials sind. Diese wollen wir nicht analysieren, und können folglich gelöscht werden.
cue | direction | practice_block_loop.thisRepN | practice_block_loop.thisTrialN | practice_block_loop.thisN | practice_block_loop.thisIndex | main_blocks_loop.thisRepN | main_blocks_loop.thisTrialN | main_blocks_loop.thisN | main_blocks_loop.thisIndex | static_isi.started | static_isi.stopped | fixation_pre.started | fixation_pre.stopped | image.started | image.stopped | fixation_post.started | fixation_post.stopped | dots_background.started | dots_background.stopped | dots_stimulus.started | dots_stimulus.stopped | dots_keyboard_response.keys | dots_keyboard_response.started | dots_keyboard_response.stopped | feedback_text.started | feedback_text.stopped | dots_keyboard_response.rt | instruction_main_text.started | instruction_main_text.stopped | instruction_main_keyboard_response.keys | instruction_main_keyboard_response.rt | instruction_main_keyboard_response.started | instruction_main_keyboard_response.stopped | Pseudonym | date | expName | psychopyVersion | frameRate |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
none | right | 0 | 0 | 0 | 5 | NA | NA | NA | NA | 0.0103343 | 2.010334 | 26.79425 | None | 27.19849 | None | 28.17814 | None | 32.18642 | None | 32.18642 | None | None | 32.18642 | None | 33.70200 | None | NA | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
left | right | 0 | 1 | 1 | 2 | NA | NA | NA | NA | 0.0320271 | 2.032027 | 36.16522 | None | 36.28205 | None | 37.28240 | None | 41.30145 | None | 41.30145 | None | f | 41.30145 | None | 42.28899 | None | 0.9339199 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
right | right | 0 | 2 | 2 | 1 | NA | NA | NA | NA | 0.0321732 | 2.032173 | 44.78521 | None | 46.00329 | None | 47.00374 | None | 52.01072 | None | 52.01072 | None | j | 52.01072 | None | 52.92295 | None | 0.8488816 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
left | left | 0 | 3 | 3 | 0 | NA | NA | NA | NA | 0.0321533 | 2.032153 | 55.39138 | None | 56.19407 | None | 57.22527 | None | 61.23181 | None | 61.23181 | None | f | 61.23181 | None | 62.21611 | None | 0.9396018 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
none | left | 0 | 4 | 4 | 4 | NA | NA | NA | NA | 0.0321391 | 2.032139 | 64.71204 | None | 64.81315 | None | 65.84603 | None | 69.25240 | None | 69.25240 | None | None | 69.25240 | None | 70.78541 | None | NA | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
right | left | 0 | 5 | 5 | 3 | NA | NA | NA | NA | 0.0323178 | 2.032318 | 73.24960 | None | 74.45209 | None | 75.48391 | None | 79.99045 | None | 79.99045 | None | f | 79.99045 | None | 80.80311 | None | 0.7490084 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 81.30346 | None | space | 3.187924 | 81.30346 | None | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
right | right | NA | NA | NA | NA | 0 | 0 | 0 | 18 | 0.0160001 | 2.016000 | 86.52245 | None | 86.89231 | None | 87.92302 | None | 92.92987 | None | 92.92987 | None | j | 92.92987 | None | 93.70924 | None | 0.7136441 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
right | right | NA | NA | NA | NA | 0 | 1 | 1 | 31 | 0.0318162 | 2.031816 | 96.17699 | None | 96.54602 | None | 97.57770 | None | 101.58423 | None | 101.58423 | None | j | 101.58423 | None | 102.26673 | None | 0.6271285 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
none | right | NA | NA | NA | NA | 0 | 2 | 2 | 66 | 0.0321148 | 2.032115 | 104.76463 | None | 105.13302 | None | 106.16508 | None | 110.67183 | None | 110.67183 | None | f | 110.67183 | None | 111.38828 | None | 0.6703410 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
none | right | NA | NA | NA | NA | 0 | 3 | 3 | 75 | 0.0321121 | 2.032112 | 113.88535 | None | 115.08794 | None | 116.11989 | None | 119.52612 | None | 119.52612 | None | j | 119.52612 | None | 120.15512 | None | 0.5738488 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
left | left | NA | NA | NA | NA | 0 | 4 | 4 | 13 | 0.0321118 | 2.032112 | 122.62295 | None | 123.82583 | None | 124.85742 | None | 129.36397 | None | 129.36397 | None | j | 129.36397 | None | 130.25975 | None | 0.8405913 | NA | NA | NA | NA | NA | NA | ZZ | 2022_Mar_07_1403 | rdk-discrimination | 03.02.21 | 59.9 |
Die Variable main_blocks_loop.thisN
ist die Trialnummer. Diese können wir verwenden, um die Zeilen auszuschliessen, die nicht zum Main Block gehören – bei den Übungstrials ist der Wert NA
.
main_blocks_loop.thisRepN | main_blocks_loop.thisTrialN | main_blocks_loop.thisN | main_blocks_loop.thisIndex |
---|---|---|---|
NA | NA | NA | NA |
NA | NA | NA | NA |
NA | NA | NA | NA |
NA | NA | NA | NA |
NA | NA | NA | NA |
NA | NA | NA | NA |
NA | NA | NA | NA |
0 | 0 | 0 | 18 |
0 | 1 | 1 | 31 |
0 | 2 | 2 | 66 |
0 | 3 | 3 | 75 |
0 | 4 | 4 | 13 |
Mit folgendem Code filtern wir zuerst, so dass , bei wir nur noch Zeilen behalten, bei denen nicht der Wert NA
in der Spalte main_blocks_loop.thisN
steht. Dann wählen wir alle Spalten ausser practice_block_loop
.
Variablen auswählen
Die folgenden Variablen enthalten Informationen zu den Inter-Trial Intervallen, Fixationskreuzen, Feedback, etc, und sind fĂĽr uns an dieser Stelle nicht interessant.
testdata |>
select(contains("static"),
contains("fixation"),
contains("image"),
contains("instruction"),
contains("feedback"))
# A tibble: 160 Ă— 16
static_isi.started static_isi.stopped fixation_pre.started
<dbl> <dbl> <dbl>
1 0.0160 2.02 86.5
2 0.0318 2.03 96.2
3 0.0321 2.03 105.
4 0.0321 2.03 114.
5 0.0321 2.03 123.
6 0.0321 2.03 133.
7 0.0321 2.03 142.
8 0.0321 2.03 152.
9 0.0321 2.03 161.
10 0.0321 2.03 172.
# â„ą 150 more rows
# â„ą 13 more variables: fixation_pre.stopped <chr>, fixation_post.started <dbl>,
# fixation_post.stopped <chr>, image.started <dbl>, image.stopped <chr>,
# instruction_main_text.started <dbl>, instruction_main_text.stopped <chr>,
# instruction_main_keyboard_response.keys <chr>,
# instruction_main_keyboard_response.rt <dbl>,
# instruction_main_keyboard_response.started <dbl>, …
Mit select
können wir alle Variablen ausser diesen auswählen.
testdata
# A tibble: 160 Ă— 19
cue direction main_blocks_loop.thisRepN main_blocks_loop.thisTrialN
<chr> <chr> <dbl> <dbl>
1 right right 0 0
2 right right 0 1
3 none right 0 2
4 none right 0 3
5 left left 0 4
6 none right 0 5
7 none left 0 6
8 left left 0 7
9 left right 0 8
10 none right 0 9
# â„ą 150 more rows
# â„ą 15 more variables: main_blocks_loop.thisN <dbl>,
# main_blocks_loop.thisIndex <dbl>, dots_background.started <dbl>,
# dots_background.stopped <chr>, dots_stimulus.started <dbl>,
# dots_stimulus.stopped <chr>, dots_keyboard_response.keys <chr>,
# dots_keyboard_response.started <dbl>, dots_keyboard_response.stopped <chr>,
# dots_keyboard_response.rt <dbl>, Pseudonym <chr>, date <chr>, …
Variablen umbenennen
Nun wollen Variablen identifizieren, die uns interessieren. Diese wollen wir umbenennen.
testdata <- testdata |>
select(trial = main_blocks_loop.thisN,
ID = Pseudonym,
cue,
direction,
response = dots_keyboard_response.keys,
rt = dots_keyboard_response.rt)
testdata
# A tibble: 160 Ă— 6
trial ID cue direction response rt
<dbl> <chr> <chr> <chr> <chr> <dbl>
1 0 ZZ right right j 0.714
2 1 ZZ right right j 0.627
3 2 ZZ none right f 0.670
4 3 ZZ none right j 0.574
5 4 ZZ left left j 0.841
6 5 ZZ none right j 0.668
7 6 ZZ none left j 1.12
8 7 ZZ left left f 0.640
9 8 ZZ left right f 1.13
10 9 ZZ none right j 1.03
# â„ą 150 more rows
Neue Variablen definieren
Nun wollen wir zwei neue Variablen erstellen: eine “character” Variable, die uns sagt, ob “rechts” oder “links” entschieden wurde, und eine numerische Variable mit derselben Information. Je nachdem, ob wir die Daten grafisch darstellen oder analysieren wollen, brauchen wir beide Variablen.
Folgender Code löst das gleiche Problem mit der Funktion as.numeric()
. Fragen Sie ruhig ChatGPT, falls Sie den Code nicht verstehen.
testdata <- testdata |>
mutate(choice = if_else(response == "j", "right", "left"),
response = as.numeric(choice == "right"))
Wir erstellen ausserdem hier eine Variable, welche angibt, ob der Cue valid
, invalid
oder neutral
war. Ein Cue ist genau dann valide, wenn er dieselbe Richtung hat wie der Random Dot Stimulus, d.h. wenn cue == direction
.
Zum Schluss erstellen wir noch eine Variable, welche festhält, ob die Antwort der Versuchsperson korrekt war.
testdata <- testdata |>
mutate(correct = as.numeric(choice == direction))
Gruppierungsvariablen
glimpse(testdata)
Rows: 160
Columns: 9
$ trial <dbl> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17…
$ ID <chr> "ZZ", "ZZ", "ZZ", "ZZ", "ZZ", "ZZ", "ZZ", "ZZ", "ZZ", "ZZ", …
$ cue <chr> "right", "right", "none", "none", "left", "none", "none", "l…
$ direction <chr> "right", "right", "right", "right", "left", "right", "left",…
$ response <dbl> 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, …
$ rt <dbl> 0.7136441, 0.6271285, 0.6703410, 0.5738488, 0.8405913, 0.667…
$ choice <chr> "right", "right", "left", "right", "right", "right", "right"…
$ condition <chr> "valid", "valid", "neutral", "neutral", "valid", "neutral", …
$ correct <dbl> 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
testdata <- testdata |>
mutate_if(is.character, as.factor)
glimpse(testdata)
Rows: 160
Columns: 9
$ trial <dbl> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17…
$ ID <fct> ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, …
$ cue <fct> right, right, none, none, left, none, none, left, left, none…
$ direction <fct> right, right, right, right, left, right, left, left, right, …
$ response <dbl> 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, …
$ rt <dbl> 0.7136441, 0.6271285, 0.6703410, 0.5738488, 0.8405913, 0.667…
$ choice <fct> right, right, left, right, right, right, right, left, left, …
$ condition <fct> valid, valid, neutral, neutral, valid, neutral, neutral, val…
$ correct <dbl> 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
Accuracy pro Bedingung
Wir können nun die accuracy in jeder Cue-Bedingung berechnen. Es gibt hier zwei Möglichkeiten: wir berechen die Anzahl Trials (N
), und die Anzahl korrekter Antworten (ncorrect
) separat. Der Anteil korrekter Antworten ist dann einfach ncorrect/N
. Dasselbe Ergebnis erhalten wir, wenn wir einfach den Mittelwert der korrekten Antworten nehmen.
testaccuracy <- testdata |>
group_by(condition) |>
summarise(N = n(),
ncorrect = sum(correct),
accuracy = ncorrect/N,
accuracy2 = mean(correct))
testaccuracy
# A tibble: 3 Ă— 5
condition N ncorrect accuracy accuracy2
<fct> <int> <dbl> <dbl> <dbl>
1 invalid 16 13 0.812 0.812
2 neutral 80 66 0.825 0.825
3 valid 64 60 0.938 0.938
Reuse
Citation
@online{ellis2023,
author = {Andrew Ellis},
title = {Daten Importieren: {Teil} 1},
date = {2023-03-13},
url = {https://kogpsy.github.io/neuroscicomplabFS23//importing_data.html},
langid = {en}
}