Beispie: LAMP-Test

In dieser Beispiel-Anal;yse sehen wir uns noch einmal die Daten zu dem LAMP-Test an, die in der ersten Vorlesung beschrieben wurden.

Einlesen einer Excel-Datei

Zunächst lesen wir die erste Platte vom ersten Worksheet der Excel-Tabelle mit den Plattenscans ein. Wir geben hier das Rechteck aus Zellen an, indem die Tabelle liegt: von Zelle A8 bis Zelle M16.

suppressPackageStartupMessages({
  library( tidyverse )
  library( readxl ) })    # readxl, um Excel-Daten laden zu können

read_excel( "~/Downloads/tecan_scans.xlsx", range="A8:M16" )
# A tibble: 8 × 13
  `*`     `1`   `2`   `3`   `4`   `5`   `6`   `7`   `8`   `9`  `10`  `11`  `12`
  <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 A      1.53  1.54  1.43  1.40  1.40  1.41  1.31  1.38  1.09  1.18  1.32  1.32
2 B      1.23  1.47  1.38  1.44  1.24  1.38  1.24  1.25  1.33  1.34  1.33  1.28
3 C      1.40  1.36  1.24  1.35  1.34  1.15  1.15  1.20  1.16  1.14  1.26  1.34
4 D      1.26  1.20  1.17  1.43  1.35  1.38  1.20  1.15  1.29  1.33  1.17  1.15
5 E      1.26  1.42  1.39  1.24  1.37  1.26  1.16  1.14  1.11  1.19  1.07  1.40
6 F      1.24  1.19  1.37  1.22  1.28  1.25  1.15  1.17  1.19  1.12  1.31  1.51
7 G      1.24  1.27  1.24  1.31  1.28  1.51  1.21  1.18  1.18  1.18  1.35  1.25
8 H      1.26  1.22  1.33  1.33  1.34  1.28  1.25  1.28  1.19  1.18  1.22  1.29

Wir machen die Tabelle “lang”:

read_excel( "~/Downloads/tecan_scans.xlsx", range="A8:M16" ) %>%
pivot_longer( cols=-"*", names_to = "plate_col" , values_to = "abs434" ) %>%
rename( "plate_row"="*" ) -> tbl434

tbl434
# A tibble: 96 × 3
   plate_row plate_col abs434
   <chr>     <chr>      <dbl>
 1 A         1           1.53
 2 A         2           1.54
 3 A         3           1.43
 4 A         4           1.40
 5 A         5           1.40
 6 A         6           1.41
 7 A         7           1.31
 8 A         8           1.38
 9 A         9           1.09
10 A         10          1.18
# ℹ 86 more rows

Hier haben wir nun Tabellenzeilen für Plattenzeile und Plattenspalte. Die Spalte mit den Werten heist nun “abs434” für “Absorption bei 434 nm”.

Dasselbe für den Scan bei 560 nm, der weiter unten im Excel-Worksheet (in Zeilen 22 bis 30) steht.

read_excel( "~/Downloads/tecan_scans.xlsx", range="A22:M30" ) %>%
pivot_longer( cols=-"*", names_to = "plate_col" , values_to = "abs560" ) %>%
rename( "plate_row"="*" ) -> tbl560

tbl560
# A tibble: 96 × 3
   plate_row plate_col abs560
   <chr>     <chr>      <dbl>
 1 A         1           1.11
 2 A         2           1.32
 3 A         3           1.05
 4 A         4           1.02
 5 A         5           1.10
 6 A         6           1.07
 7 A         7           1.20
 8 A         8           1.19
 9 A         9           1.51
10 A         10          1.52
# ℹ 86 more rows

Joining

Wir fügen die beiden Tabellen zusammen

full_join( tbl434, tbl560, by=c( "plate_row", "plate_col" ) )     # ("left_join" geht auch)
# A tibble: 96 × 4
   plate_row plate_col abs434 abs560
   <chr>     <chr>      <dbl>  <dbl>
 1 A         1           1.53   1.11
 2 A         2           1.54   1.32
 3 A         3           1.43   1.05
 4 A         4           1.40   1.02
 5 A         5           1.40   1.10
 6 A         6           1.41   1.07
 7 A         7           1.31   1.20
 8 A         8           1.38   1.19
 9 A         9           1.09   1.51
10 A         10          1.18   1.52
# ℹ 86 more rows

Mit by haben wir angegeben, an welchen Spalten der Join erkennt, welche Zeilen zusammengefügt werden sollen.

Die übrigen Worksheets

Die was das erste Sheet, beschriftet mit “20 min”. Um ein anderes Sheet, z.B. das für Inkubationszeit “25 min” zu erhalten, müssen wir ein sheet-Argument mit angeben:

read_excel( "~/Downloads/tecan_scans.xlsx", range="A8:M16", sheet="25 min" )
# A tibble: 8 × 13
  `*`     `1`   `2`   `3`   `4`   `5`   `6`   `7`   `8`   `9`  `10`  `11`  `12`
  <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 A      1.52  1.66  1.44  1.44  1.49  1.43  1.39  1.48  1.12  1.18  1.41  1.43
2 B      1.30  1.50  1.42  1.50  1.25  1.46  1.39  1.29  1.41  1.41  1.41  1.31
3 C      1.46  1.47  1.27  1.40  1.41  1.16  1.16  1.21  1.29  1.16  1.25  1.39
4 D      1.31  1.23  1.21  1.52  1.45  1.45  1.20  1.16  1.36  1.39  1.19  1.18
5 E      1.29  1.45  1.44  1.26  1.44  1.28  1.16  1.15  1.13  1.23  1.11  1.45
6 F      1.27  1.20  1.49  1.23  1.39  1.36  1.18  1.18  1.21  1.12  1.34  1.56
7 G      1.27  1.29  1.26  1.31  1.41  1.48  1.18  1.19  1.20  1.16  1.38  1.29
8 H      1.26  1.24  1.34  1.35  1.35  1.30  1.28  1.45  1.22  1.17  1.26  1.31

Wenn wir die Inkubationszeit in Minuten haben (z.B. minutes=25), können wir den Sheet-Namen mit str_c zusammensetzen:

minutes <- 25
sheet <- str_c( minutes, " min" )

sheet
[1] "25 min"

Wir bilden aus den Code-Zeilen, die wir bisher haben, eine Funktion:

load_sheet <- function( minutes ) {
 
  sheet <- str_c( minutes, " min" )
   
  read_excel( "~/Downloads/tecan_scans.xlsx", range="A8:M16", sheet=sheet ) %>%
  pivot_longer( cols=-"*", names_to = "plate_col" , values_to = "abs434" ) %>%
  rename( "plate_row"="*" ) -> tbl434
  
  read_excel( "~/Downloads/tecan_scans.xlsx", range="A22:M30", sheet=sheet ) %>%
  pivot_longer( cols=-"*", names_to = "plate_col" , values_to = "abs560" ) %>%
  rename( "plate_row"="*" ) -> tbl560
  
  full_join( tbl434, tbl560, by=c( "plate_row", "plate_col" ) ) %>%
  mutate( time = minutes )

}

Diese Funktion können wir nun aufrufen, mit Angabe einer Inkubationszeit, und sie lädt das zugehörige Worksheet, und baut die Tabelle zusammen.

load_sheet( 30 )
# A tibble: 96 × 5
   plate_row plate_col abs434 abs560  time
   <chr>     <chr>      <dbl>  <dbl> <dbl>
 1 A         1           1.52  1.01     30
 2 A         2           1.55  1.10     30
 3 A         3           1.43  0.978    30
 4 A         4           1.44  0.972    30
 5 A         5           1.44  0.980    30
 6 A         6           1.43  0.973    30
 7 A         7           1.37  0.953    30
 8 A         8           1.43  0.989    30
 9 A         9           1.16  1.59     30
10 A         10          1.18  1.56     30
# ℹ 86 more rows

In der Funktion haben wir dem Join eine Code-Zeile angefügt, der die Minuten-Zahl in einer neuen Spalte time einträgt.

Alle Sheets laden

Damit können wir nun alle Sheets laden und mit bind_rows zu eienr langen Tabelle zusammen fügen:

bind_rows(
  load_sheet( 20 ),
  load_sheet( 25 ),
  load_sheet( 30 ),
  load_sheet( 35 ),
  load_sheet( 40 ),
  load_sheet( 45 )
) -> lamp_table

lamp_table
# A tibble: 576 × 5
   plate_row plate_col abs434 abs560  time
   <chr>     <chr>      <dbl>  <dbl> <dbl>
 1 A         1           1.53   1.11    20
 2 A         2           1.54   1.32    20
 3 A         3           1.43   1.05    20
 4 A         4           1.40   1.02    20
 5 A         5           1.40   1.10    20
 6 A         6           1.41   1.07    20
 7 A         7           1.31   1.20    20
 8 A         8           1.38   1.19    20
 9 A         9           1.09   1.51    20
10 A         10          1.18   1.52    20
# ℹ 566 more rows

WIr können auch

seq( 20, 45, 5 )
[1] 20 25 30 35 40 45

verwenden, um alle Zeiten zu erzeugen, und dann die Funktion für jede Zeit aufrufen. Wenn man das mit map_dfr macht, werden die Ergebnisse wie zuvor zu einer langen Tabelle zusammengestellt:

map_dfr( seq( 20, 45, 5 ), load_sheet ) -> lamp_table

Plot

Als Vorbereitung zum Plotten fügen wir eine Spalte well hinzu, die Platten-Zeile und -Spalte zusammenfügt:

lamp_table %>%
mutate( well = str_c( plate_row, plate_col ) )
# A tibble: 576 × 6
   plate_row plate_col abs434 abs560  time well 
   <chr>     <chr>      <dbl>  <dbl> <dbl> <chr>
 1 A         1           1.53   1.11    20 A1   
 2 A         2           1.54   1.32    20 A2   
 3 A         3           1.43   1.05    20 A3   
 4 A         4           1.40   1.02    20 A4   
 5 A         5           1.40   1.10    20 A5   
 6 A         6           1.41   1.07    20 A6   
 7 A         7           1.31   1.20    20 A7   
 8 A         8           1.38   1.19    20 A8   
 9 A         9           1.09   1.51    20 A9   
10 A         10          1.18   1.52    20 A10  
# ℹ 566 more rows

Nun können wir plotten. Jedes Well wird durch eine Linie dargestellt:

lamp_table %>%
mutate( well = str_c( plate_row, plate_col ) ) %>%
ggplot +
  geom_line( aes( x=time, y=abs434-abs560, group=well ) )