# Start the multiblock R package
library(multiblock)
#> Registered S3 methods overwritten by 'multiblock':
#> method from
#> print.multiblock ade4
#> summary.multiblock ade4
#>
#> Attaching package: 'multiblock'
#> The following object is masked from 'package:stats':
#>
#> loadings
Data are stored in many different file formats. The following three examples cover two types of CSV-files and generic flat files.
# Find directory extdata from the multiblock package
<- system.file('extdata/', package = "multiblock")
mbdir
# Comma separated values, row names in first column
<- read.csv(paste0(mbdir, "/meta_data.csv"), row.names = 1)
meta_data # If working directory matches file location:
# meta_data <- read.csv('meta_data.csv', row.names = 1)
meta_data#> temperature colour
#> John 38.0 blue
#> Julia 37.0 green
#> James 37.5 blue
#> Jacob 37.6 red
#> Jane 37.2 red
#> Johanna 37.9 green
# Semi-colon separated values (locales where the decimal point is comma),
# no row names
<- read.csv2(paste0(mbdir, "/proteins.csv"))
proteins
proteins#> prot1 prot2 prot3
#> 1 0.46532048 0.30183300 -1.4654414
#> 2 -1.79802081 -0.22812232 -0.4639203
#> 3 -1.92962434 -0.40513080 0.1767796
#> 4 0.87437138 0.79843798 0.1234731
#> 5 -0.62445278 -0.07975479 -1.1126332
#> 6 -0.07493721 1.09576027 1.2656596
# Blank space separated data without labels
<- read.table(paste0(mbdir, "/genes.dat"))
genes
genes#> V1 V2 V3
#> 1 0.39033106 -0.5720390 1.9147573
#> 2 0.55352785 0.0948703 -0.2239755
#> 3 0.09872346 -0.1029385 0.9047138
#> 4 -0.59213740 -0.6027739 0.6177083
#> 5 -0.02350148 0.3572809 -0.5168416
#> 6 0.76644845 1.2863428 1.8239298
Before analysis, various types of pre-processing may be needed. Centring and standardising/scaling may be considered the most basic. In R, these operations are performed column-wise by default, leading to autoscaling. If these operations are performed on the rows, we perform the standard normal variate (SNV) instead.
# Column-centring
<- scale(genes, scale=FALSE)
genes_centred colMeans(genes_centred) # Check mean values
#> V1 V2 V3
#> 1.850372e-17 0.000000e+00 7.401487e-17
# Autoscaling
<- scale(genes)
genes_scaled apply(genes_scaled, 2, sd) # Check standard deviations
#> V1 V2 V3
#> 1 1 1
# SNV (transpose, autoscale, re-transpose)
<- t(scale(t(genes)))
genes_snv apply(genes_snv, 1, sd) # Check standard deviations
#> [1] 1 1 1 1 1 1
Most analysis methods require continuous input data. The meta_data data.frame contains a character vector (a factor in older R versions) of categories. This package has a function dummycode for converting categorical data to various dummy formats.
# Default is sum coding
dummycode(meta_data$colour)
#> x1 x2
#> 1 1 0
#> 2 0 1
#> 3 1 0
#> 4 -1 -1
#> 5 -1 -1
#> 6 0 1
# Treatment coding
dummycode(meta_data$colour, "contr.treatment")
#> xgreen xred
#> 1 0 0
#> 2 1 0
#> 3 0 0
#> 4 0 1
#> 5 0 1
#> 6 1 0
# Full dummy-coding (rank deficient)
dummycode(meta_data$colour, drop = FALSE)
#> xblue xgreen xred
#> 1 1 0 0
#> 2 0 1 0
#> 3 1 0 0
#> 4 0 0 1
#> 5 0 0 1
#> 6 0 1 0
# Replace categorical with dummy-coded, use I() to index by common name
<- meta_data
meta_data2 $colour <- I(dummycode(meta_data$colour, drop = FALSE))
meta_data2
meta_data2#> temperature colour.xblue colour.xgreen colour.xred
#> John 38.0 1 0 0
#> Julia 37.0 0 1 0
#> James 37.5 1 0 0
#> Jacob 37.6 0 0 1
#> Jane 37.2 0 0 1
#> Johanna 37.9 0 1 0
$colour
meta_data2#> xblue xgreen xred
#> 1 1 0 0
#> 2 0 1 0
#> 3 1 0 0
#> 4 0 0 1
#> 5 0 0 1
#> 6 0 1 0
A simple list of blocks can be created using the list() function. Naming of the blocks can be done directly or after creation.
# Direct approach
<- list(meta = meta_data2, proteins = proteins, genes = genes)
blocks1
# Two-step approach
<- list(meta_data2, proteins, genes)
blocks2 names(blocks2) <- c('meta', 'proteins', 'genes')
# Same result
identical(blocks1, blocks2)
#> [1] TRUE
# Access by name or number
'meta']]
blocks1[[#> temperature colour.xblue colour.xgreen colour.xred
#> John 38.0 1 0 0
#> Julia 37.0 0 1 0
#> James 37.5 1 0 0
#> Jacob 37.6 0 0 1
#> Jane 37.2 0 0 1
#> Johanna 37.9 0 1 0
1]]
blocks2[[#> temperature colour.xblue colour.xgreen colour.xred
#> John 38.0 1 0 0
#> Julia 37.0 0 1 0
#> James 37.5 1 0 0
#> Jacob 37.6 0 0 1
#> Jane 37.2 0 0 1
#> Johanna 37.9 0 1 0
A data.frame is a convenient storage format for data in R and can handle many types of variables, e.g. numeric, logical, character, factor or matrices. The latter is useful for analyses of data with shared sample mode.
# Construct block data.frame from list
<- block.data.frame(blocks1)
df1
# Construct block data.frame from data.frame:
# First merge blocks into data.frame
<- cbind(meta_data2, proteins, genes)
my_data # Then construct block data.frame using named
# list of indexes
<- block.data.frame(my_data, block_inds =
df2 list(meta = 1:2, proteins = 3:5, genes = 6:8))
# Same result
identical(df1,df2)
#> [1] TRUE
# Access by name or number
2]]
df1[[#> prot1 prot2 prot3
#> John 0.46532048 0.30183300 -1.4654414
#> Julia -1.79802081 -0.22812232 -0.4639203
#> James -1.92962434 -0.40513080 0.1767796
#> Jacob 0.87437138 0.79843798 0.1234731
#> Jane -0.62445278 -0.07975479 -1.1126332
#> Johanna -0.07493721 1.09576027 1.2656596
'proteins']]
df2[[#> prot1 prot2 prot3
#> John 0.46532048 0.30183300 -1.4654414
#> Julia -1.79802081 -0.22812232 -0.4639203
#> James -1.92962434 -0.40513080 0.1767796
#> Jacob 0.87437138 0.79843798 0.1234731
#> Jane -0.62445278 -0.07975479 -1.1126332
#> Johanna -0.07493721 1.09576027 1.2656596
c(1,3)]
df1[#> $meta
#> temperature colour.xblue colour.xgreen colour.xred
#> John 38.0 1 0 0
#> Julia 37.0 0 1 0
#> James 37.5 1 0 0
#> Jacob 37.6 0 0 1
#> Jane 37.2 0 0 1
#> Johanna 37.9 0 1 0
#>
#> $genes
#> V1 V2 V3
#> John 0.39033106 -0.5720390 1.9147573
#> Julia 0.55352785 0.0948703 -0.2239755
#> James 0.09872346 -0.1029385 0.9047138
#> Jacob -0.59213740 -0.6027739 0.6177083
#> Jane -0.02350148 0.3572809 -0.5168416
#> Johanna 0.76644845 1.2863428 1.8239298
-2]
df1[#> $meta
#> temperature colour.xblue colour.xgreen colour.xred
#> John 38.0 1 0 0
#> Julia 37.0 0 1 0
#> James 37.5 1 0 0
#> Jacob 37.6 0 0 1
#> Jane 37.2 0 0 1
#> Johanna 37.9 0 1 0
#>
#> $genes
#> V1 V2 V3
#> John 0.39033106 -0.5720390 1.9147573
#> Julia 0.55352785 0.0948703 -0.2239755
#> James 0.09872346 -0.1029385 0.9047138
#> Jacob -0.59213740 -0.6027739 0.6177083
#> Jane -0.02350148 0.3572809 -0.5168416
#> Johanna 0.76644845 1.2863428 1.8239298
c('proteins','genes')]
df2[#> $proteins
#> prot1 prot2 prot3
#> John 0.46532048 0.30183300 -1.4654414
#> Julia -1.79802081 -0.22812232 -0.4639203
#> James -1.92962434 -0.40513080 0.1767796
#> Jacob 0.87437138 0.79843798 0.1234731
#> Jane -0.62445278 -0.07975479 -1.1126332
#> Johanna -0.07493721 1.09576027 1.2656596
#>
#> $genes
#> V1 V2 V3
#> John 0.39033106 -0.5720390 1.9147573
#> Julia 0.55352785 0.0948703 -0.2239755
#> James 0.09872346 -0.1029385 0.9047138
#> Jacob -0.59213740 -0.6027739 0.6177083
#> Jane -0.02350148 0.3572809 -0.5168416
#> Johanna 0.76644845 1.2863428 1.8239298
# Use with formula interface (see other vignettes)
# sopls(meta ~ proteins + genes, data = df1)
# Use with single list interface (see other vignettes)
# mfa(df1[c(1,3)], ncomp = 3)