Daten importieren: Teil 1

Daten aus Verhaltensexperimenten importieren und bearbeiten.
Published

March 13, 2023

Lernziele

In der heutigen Sitzung lernen wir:

  • Mit RStudio arbeiten
  • Einzelne Psychopy .csv Datensätze importieren
  • Variablen auswählen/umbenennen
  • Neue Variablen berechnen
  • Mehrere Datensätze importieren
  • Mit ChatGPT Code verstehen
  • Falls Sie eine Starthilfe zu RStudio brauchen, empfehlen wir dieses RStudio Tutorial.
  • Falls Sie mir R und den tidyverse Packages (noch) nicht sattelfest sind, empfehlen wir Ihnen das erste Kapitel im folgenden Kurs auf DataCamp: Introduction to the Tidyverse.

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.

Lösung

Ă–ffnen Sie ZZ_rdk-discrimination_2022_Mar_07_1403.csv in Excel.

Was steht in den Spalten? Was steht in den Zeilen?

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.

testdata <- testdata |> 
    filter(!is.na(main_blocks_loop.thisN)) |>
    select(-contains("practice_block_loop"))
ChatGPT

Falls Code nicht verständlich finden, können Sie ChatGPT fragen. Benutzen Sie folgenden Prompt:

What does the following R code do? 

testdata <- testdata |> 
    filter(!is.na(main_blocks_loop.thisN)) |>
    select(-contains("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 <- testdata |>
    select(-contains("static"),
           -contains("fixation"),
           -contains("image"),
           -contains("instruction"),
           -contains("feedback"))
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.

testdata <- testdata |>
    mutate(choice = if_else(response == "j", "right", "left"),
           response = if_else(choice == "right", 1, 0))

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.

testdata <- testdata |>
    mutate(condition = case_when(cue == "none" ~ "neutral",
                                 cue == direction ~ "valid",
                                 cue != direction ~ "invalid"))
ChatGPT

What does the R function case_when() do?

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

BibTeX 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}
}
For attribution, please cite this work as:
Andrew Ellis. 2023. “Daten Importieren: Teil 1.” March 13, 2023. https://kogpsy.github.io/neuroscicomplabFS23//importing_data.html.