# Reconstructing an observed $2 \times 3$ contingency table

Let an observed $2 \times 3$ contingency table be

$$\begin{array}{c|ccc|c} v_1 \backslash v_2 & 0 & 1 & 2 & \\ \hline 0 & m_0 & m_1 & m_2 & m \\ 1 & ? & ? & ? & n \\ \hline & ? & ? & ? & m + n \end{array}$$

where $m_0$, $m_1$, $m_2$, $m$ and $n$ are known values. Is there a way to reconstruct the whole table if, besides those values, we know the $\chi_2^2$ test statistic between the two categorical variables $v_1$ and $v_2$?

I don't think so. You have two unkowns: Once you have two of the cell counts, you can compute all the other questionmarks. The $\chi^2$ statistic is one bit of information, so that is not enough.

• It may be enough in some situations, see my answer. Commented Aug 20, 2023 at 9:35

Maybe if you're lucky, but the problem is that there is no guarantee that a unique table satisfies these constraints.

I can't tell for analytical methods, but you could try numerical methods to find out if there's a unique solution, and if so, what it is.

For example, if your sample size is not too large, you could use brute-force search by generating all possible permutations satisfying the row sum constraint, and then filter those satifying the chi-square constraint (you can think of it as trying to break a password by trying all possible solutions). I give an example at the end of this answer showing how to do that in R.

Brute force is a "dumb" method, but you're guaranteed to find at least one solution, unless some information you have about the table is erroneous - which is something not to be dismissed: why would you have a table with partial information like that? If it's because someone is voluntarily withholding information, they might have also slightly altered the few information they gave, in order to protect sensitive information and to make it impossible to reconstruct the original table.

Besides brute force, you could use some optimization or root-finding algorithm that would be more efficient than brute force search, time-wise. The most optimal method is probably more a question for https://stackoverflow.com or https://cs.stackexchange.com, I guess.

However, as mentioned before (and besides possible computational issues with large sample sizes), a problem is that different tables might satisfy your constraints. If you're in this case, it's impossible to reconstruct the original table with certainty.

Consider for example these two tables, with the same first row, the same marginal row totals, and the same $$\chi^2$$ statistic ($$53.06...$$), but with a different distribution in the second row:

v1/v2 0 1 2 Total
0 12 7 98 117
1 20 56 53 129
v1/v2 0 1 2 Total
0 12 7 98 117
1 69 7 53 129

So you see that with certain tables and constraints, there may be no unique solution to your problem.

On the other hand, there are cases where there might be a unique solution (i.e. a single row satisfying all the constraints). Here is an example showing how to find this unique solution, with the programming language R.

We have a 2x3 table where the first row is known (100, 35, 120) as well as the marginal row sums (200 for the second row) and the chi-squared statistic ($$\approx208.268$$), but we don't know the distribution of the second row:

v1/v2 0 1 2 Total
0 100 35 120 255
1 ? ? ? 200

We use the package RcppAlgos to generate all possible permutations of 3 non-negative integers summing to 200:

library(RcppAlgos)
sumRow2 = 200
compos = compositionsGeneral(0:sumRow2, 3, repetition = TRUE, weak=T)
nrow(compos)
>20301


There are 20301 possible permutations satisfying this sum constraint; with a modern computer, it should take just some seconds to find the solution if there is one among these 20301 candidates. We plug each of these permutations in the contingency table, to generate 20301 possible chi-squared values:

chis = c()
row1 = c(100,35,120)
for (n.comp in 1:nrow(compos) ) {
row2 = compos[n.comp,]
tab = rbind(row1, row2)
res = chisq.test(tab)
chis = c(chis, res$statistic) }  As the chi-squared value we have is an approximation ($$\approx208.268$$), we try to find which one is > 208.267 and < 208.269 in the list of generated chi-squared values (stored in the chis vector): which(chis > 208.267 & chis < 208.269) >157  Luckily, there is a single one result, located at the index 157 of the vector. (With two or more results, it would have been impossible to reconstruct the original table with certainty). We take a look at the index 157 of the compos variable, which stores all possible permutations summing to 200: compos[157,] [1] 0 156 44  So the row (0, 156, 44) is the one satisfying the constraints, so the table is: v1/v2 0 1 2 Total 0 100 35 120 255 1 0 156 44 200 We can double check if the chi-square statistic matches the one we had ($$\approx208.268$$): tab = rbind(c(100,35,120), c(0,156,44)) chisq.test(tab)$statistic
X-squared
208.2688