# How to remedy a DESeq2 collapsing technical replicates error?

Goal: To ensure "the sum of the counts for [my samples] is the same as the counts in the [samples] columns in ddsColl" after collapsing replicates using DESeq2.

Before performing differential expression (DE) analysis on my RNA-seq data stored in a DESeqDataSet object, I need to collapse the read counts observed for each of my technical replicates. This should be simple enough using the DESeq2 manual and vignettes available as reference.

This is how you collapse replicates:

ddsColl <- collapseReplicates(dds, dds$$sample, dds$$run)
# examine the colData of the collapsed data
colData(ddsColl)
# check that the sum of the counts for "sample1" is the same
# as the counts in the "sample1" column in ddsColl
matchFirstLevel <- dds$$sample == levels(dds$$sample)[1]
stopifnot(all(rowSums(counts(dds[,matchFirstLevel])) == counts(ddsColl[,1])))


However, when I try this, I get the following error with no apparent resolution reported in the manual or on online forums:

Error: all(rowSums(counts(dds[, matchFirstLevel])) == counts(ddsColl[,  .... is not TRUE


How might I circumvent this error and continue on with the analysis?

Input files:

> head(cts)
KO1_P1_L001.Counts KO1_P1_L002.Counts KO1_P2_L001.Counts KO1_P2_L002.Counts KO1_P3_L001.Counts KO1_P3_L002.Counts KO2_P1_L001.Counts KO2_P1_L002.Counts KO2_P2_L001.Counts KO2_P2_L002.Counts KO2_P3_L001.Counts KO2_P3_L002.Counts WT_P1_L001.Counts WT_P1_L002.Counts WT_P2_L001.Counts WT_P2_L002.Counts WT_P3_L001.Counts WT_P3_L002.Counts
DDX11L1                      1                  0                  1                  1                  2                  1                  0                  1                  2                  1                  3                  1                 7                 2                 1                 1                 0                 0
WASH7P                     124                144                128                151                102                118                 39                 41                103                 87                105                106               125               120                13                26               104               136
MIR6859-1                    8                  6                  4                  5                  4                  6                  2                  2                  7                  2                  7                  6                 6                 6                 2                 2                 2                 9
MIR1302-2HG                  1                  4                  0                  0                  0                  2                  2                  2                  2                  2                  0                  4                 1                 2                 0                 3                 2                 2
MIR1302-2                    0                  0                  0                  0                  0                  0                  0                  0                  0                  0                  0                  0                 0                 0                 0                 0                 0                 0
FAM138A                      0                  0                  0                  0                  0                  0                  0                  0                  0                  0                  0                  0                 0                 0                 0                 0                 0                 0

> print(coldata)
condition sample           run
KO1_P1_L001.Counts    longKO     l1  long_P1_L001
KO1_P1_L002.Counts    longKO     l1  long_P1_L002
KO1_P2_L001.Counts    longKO     l2  long_P2_L001
KO1_P2_L002.Counts    longKO     l2  long_P2_L002
KO1_P3_L001.Counts    longKO     l3  long_P3_L001
KO1_P3_L002.Counts    longKO     l3  long_P3_L002
KO2_P1_L001.Counts   shortKO     s1 short_P1_L001
KO2_P1_L002.Counts   shortKO     s1 short_P1_L002
KO2_P2_L001.Counts   shortKO     s2 short_P2_L001
KO2_P2_L002.Counts   shortKO     s2 short_P2_L002
KO2_P3_L001.Counts   shortKO     s3 short_P3_L001
KO2_P3_L002.Counts   shortKO     s3 short_P3_L002
WT_P1_L001.Counts         WT     w1    wt_P1_L001
WT_P1_L002.Counts         WT     w1    wt_P1_L002
WT_P2_L001.Counts         WT     w2    wt_P2_L001
WT_P2_L002.Counts         WT     w2    wt_P2_L002
WT_P3_L001.Counts         WT     w3    wt_P3_L001
WT_P3_L002.Counts         WT     w3    wt_P3_L002


My workflow:

> dds <- DESeqDataSetFromMatrix(countData = cts, colData = coldata, design = ~ condition)
> ddsColl <- collapseReplicates(dds, dds$$sample, dds$$run)
> colData(ddsColl)
DataFrame with 9 rows and 4 columns
condition      sample           run               runsCollapsed
<factor> <character>   <character>                 <character>
l1    longKO          l1  long_P1_L001   long_P1_L001,long_P1_L002
l2    longKO          l2  long_P2_L001   long_P2_L001,long_P2_L002
l3    longKO          l3  long_P3_L001   long_P3_L001,long_P3_L002
s1   shortKO          s1 short_P1_L001 short_P1_L001,short_P1_L002
s2   shortKO          s2 short_P2_L001 short_P2_L001,short_P2_L002
s3   shortKO          s3 short_P3_L001 short_P3_L001,short_P3_L002
w1        WT          w1    wt_P1_L001       wt_P1_L001,wt_P1_L002
w2        WT          w2    wt_P2_L001       wt_P2_L001,wt_P2_L002
w3        WT          w3    wt_P3_L001       wt_P3_L001,wt_P3_L002

> matchFirstLevel <- dds$$sample == levels(dds$$sample)[1]
> matchFirstLevel
logical(0)

> stopifnot(all(rowSums(counts(dds[,matchFirstLevel])) == counts(ddsColl[,1])))
Error: all(rowSums(counts(dds[, matchFirstLevel])) == counts(ddsColl[,  .... is not TRUE


From the output of dds and ddsColl, it seems the number of columns decreased from 18 to 9, as expected. The only difference I see between my DESeq2 workflow output is the result of matchFirstLevel (see below for expected result). Why might this be for my dataset, but not the example dataset?

Example workflow:

> dds <- makeExampleDESeqDataSet(m=12)
> dds$$sample <- factor(sample(paste0("sample",rep(1:9, c(2,1,1,2,1,1,2,1,1))))) > dds$$run <- paste0("run",1:12)
> ddsColl <- collapseReplicates(dds, dds$$sample, dds$$run)
> colData(ddsColl)
DataFrame with 9 rows and 4 columns
condition   sample         run runsCollapsed
<factor> <factor> <character>   <character>
sample1         B  sample1       run10   run10,run11
sample2         A  sample2        run5          run5
sample3         A  sample3        run6          run6
sample4         A  sample4        run1     run1,run4
sample5         B  sample5        run7          run7
sample6         B  sample6        run9          run9
sample7         A  sample7        run3    run3,run12
sample8         B  sample8        run8          run8
sample9         A  sample9        run2          run2

> matchFirstLevel <- dds$$sample == levels(dds$$sample)[1]
> matchFirstLevel
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE

> stopifnot(all(rowSums(counts(dds[,matchFirstLevel])) == counts(ddsColl[,1])))

• tl;dr -- please make the question short and precise. Jan 13 at 10:26
• Very fair. I wanted to include my input data for reference and reproducibility, but perhaps it makes the content look too daunting/long? I tried to clean it up a little. I think the outputs of the console commands are still necessary because they provide important info for comparison between observed and expected outcomes. Jan 13 at 15:14
• @Gawain It's best to remove lines like colnames(ddsColl) and read.table(...) since it doesn't affect other people's understanding of the analysis, presumably it's only there for your benefit. Only include lines of code which are exactly necessary for others to understand the analysis you did. Jan 13 at 15:44
• @user438383 I see your reasoning; I have removed those lines from the content :) Jan 13 at 17:25

sample is a character vector, so levels(dds$sample) is returning null. Presumably you mean to use dds$sample[1] here instead, which will likely solve the problem.
• This worked for me! Indeed, in my dataset, sample is a character vector, and in the example dataset, sample is a factor. That would explain why the example code was not working for me. Replacing levels(dds$sample) with dds$sample[1] in the matchFirstLevel variable creation line fixed the problem. Jan 14 at 13:17