# Why is the Spearman or other type of correlation in R is unable to produce p values on only two datapoints?

Why is the Spearman or other type of correlation in R is unable to produce p values on only two data points?

I would like to do correlation with only two observations and produce p vlues of significance. However, in R, any type of correlation (pearson, spearman, kendall's tau), is unable to produce p values of just 2 observations.

There is a nice explanation why correlation of just 2 observations will result -1 or +1 but not why p values are unable to be calculated:Why is the Pearson correlation 1 when only two data values are available?

Example:

corr.test(c(1,2), c(3,4))$p [1] NaN Warning messages: 1: In corr.test(c(1, 2), c(3, 4)) : Number of subjects must be greater than 3 to find confidence intervals. 2: In sqrt(n - 3) : NaNs produced  is it because p-value is calculated using a t-distribution with n - 2 degrees of freedom ? The formula for the test statistic is t=rn−2√1−r2√ . Then, what is an alternative to produce such significance? If I reduce n-2 to just "n-1"? What will be the negative side? R formula of "corr.test" t <- (r * sqrt(n - 2))/sqrt(1 - r^2) p <- -2 * expm1(pt(abs(t), (n - 2), log.p = TRUE)) se <- sqrt((1 - r * r)/(n - 2))  If the only possible r correlation coefficient values between of just two observations are -1, 0, and 1, then the possible pvalues with (n-1 AND not n-2) is: --- Which produces division with zero error. Note: t.student distribution was used with df=1 to produce in librecalc pvalues. To counteract that, then we may adjust r correlation coefficient 1 to 0.99 and 1 to -.99. Then, pvalues on t-student distribution is produced with no div/0! error. Note: t.student distribution was used with df=1 to produce in librecalc pvalues. *Edit Note, in the images, the whole calculation inside "sqrt" at numerator, is "1 * SQRT(2-1) = 1 * SQRT(1)= 1". • Re: "I would like to do correlation with only two observations and produce p values of significance:" That's possible only if you are performing one-sided tests with a threshold$\alpha$of 50% or greater. – whuber Aug 10, 2020 at 16:53 • Can you elaborate on that and how I can run it on R? Aug 10, 2020 at 16:54 • Sure: if your null hypothesis is zero correlation and the alternative is (for example) that the correlation is positive, then observing a negative slope is a tiny bit of evidence against the alternative. Because the chance of a negative slope (assuming a continuous probability distribution of the residuals) is 50% under the null, by definition the p-value is 50%. (If you observe a positive slope, the p-value is 100%.) You will have no trouble writing an R function to do this calculation! If you need further explanation, see stats.stackexchange.com/questions/tagged/p-value?tab=Votes. – whuber Aug 10, 2020 at 16:58 • Re the edit: if you change$n-2$to$n-1$in the calculation, you will get the wrong p-value, that's all. – whuber Aug 10, 2020 at 17:38 • Why are you finding the correlation between two points? You always can draw a straight line through two points. The correlation is either a perfect 1 or -1. – Dave Aug 10, 2020 at 17:46 ## 1 Answer Finally, what I did. I changed the R function corr.test:  r <- r/1.001 t <- (r * sqrt(n - 1))/sqrt(1 - r^2) p <- -2 * expm1(pt(abs(t), (n - 1), log.p = TRUE))  a) I changed the Formula: where n-2 became n-1 in order to remove "0" from numerator. b) I divided the whole r correlation coefficient matrix with r/1.001 in order to change "1" or "-1" values into 0.9999 or - 0.999, in order to remove "division by zero" error (denumerator thing). ---Then it is possible to produce "r values" and "p values" of just two observations. ---I know that the result will be not have much "generability", but just correlating two observations per case do not have much generability, anyhow! corr_tst_2obs <-function (x, y = NULL, use = "pairwise", method = "pearson", adjust = "holm", alpha = 0.05, ci = TRUE, minlength = 5) { cl <- match.call() if (is.null(y)) { r <- cor(x, use = use, method = method) sym <- TRUE n <- t(!is.na(x)) %*% (!is.na(x)) } else { r <- cor(x, y, use = use, method = method) sym = FALSE n <- t(!is.na(x)) %*% (!is.na(y)) } if ((use == "complete") | (min(n) == max(n))) n <- min(n) r <- r/1.001 t <- (r * sqrt(n - 1))/sqrt(1 - r^2) p <- -2 * expm1(pt(abs(t), (n - 1), log.p = TRUE)) se <- sqrt((1 - r * r)/(n - 2)) nvar <- ncol(r) p[p > 1] <- 1 if (adjust != "none") { if (is.null(y)) { lp <- upper.tri(p) pa <- p[lp] pa <- p.adjust(pa, adjust) p[upper.tri(p, diag = FALSE)] <- pa } else { p[] <- p.adjust(p, adjust) } } z <- fisherz(r[lower.tri(r)]) if (ci) { if (min(n) < 4) { warning("Number of subjects must be greater than 3 to find confidence intervals.") } if (sym) { ncors <- nvar * (nvar - 1)/2 } else ncors <- prod(dim(r)) if (adjust != "holm") { dif.corrected <- qnorm(1 - alpha/(2 * ncors)) } else { ord <- order(abs(z), decreasing = FALSE) dif.corrected <- qnorm(1 - alpha/(2 * order(ord))) } alpha <- 1 - alpha/2 dif <- qnorm(alpha) if (sym) { if (is.matrix(n)) { sef <- 1/sqrt(n[lower.tri(n)] - 3) } else { sef <- 1/sqrt(n - 3) } lower <- fisherz2r(z - dif * sef) upper <- fisherz2r(z + dif * sef) lower.corrected <- fisherz2r(z - dif.corrected * sef) upper.corrected <- fisherz2r(z + dif.corrected * sef) ci <- data.frame(lower = lower, r = r[lower.tri(r)], upper = upper, p = p[lower.tri(p)]) ci.adj <- data.frame(lower.adj = lower.corrected, upper.adj = upper.corrected) cnR <- abbreviate(colnames(r), minlength = minlength) k <- 1 for (i in 1:(nvar - 1)) { for (j in (i + 1):nvar) { rownames(ci)[k] <- paste(cnR[i], cnR[j], sep = "-") k <- k + 1 } } } else { n.x <- NCOL(x) n.y <- NCOL(y) z <- fisherz(r) if (adjust != "holm") { dif.corrected <- qnorm(1 - (1 - alpha)/(n.x * n.y)) } else { ord <- order(abs(z), decreasing = FALSE) dif.corrected <- qnorm(1 - (1 - alpha)/(order(ord))) } sef <- 1/sqrt(n - 3) lower <- as.vector(fisherz2r(z - dif * sef)) upper <- as.vector(fisherz2r(z + dif * sef)) lower.corrected <- fisherz2r(z - dif.corrected * sef) upper.corrected <- fisherz2r(z + dif.corrected * sef) ci <- data.frame(lower = lower, r = as.vector(r), upper = upper, p = as.vector(p)) ci.adj <- data.frame(lower.adj = as.vector(lower.corrected), r = as.vector(r), upper.adj = as.vector(upper.corrected)) cnR <- abbreviate(rownames(r), minlength = minlength) cnC <- abbreviate(colnames(r), minlength = minlength) k <- 1 for (i in 1:NCOL(y)) { for (j in 1:NCOL(x)) { rownames(ci)[k] <- paste(cnR[j], cnC[i], sep = "-") k <- k + 1 } } } } else { ci <- sef <- ci.adj <- NULL } result <- list(r = r, n = n, t = t, p = p, se = se, sef = sef, adjust = adjust, sym = sym, ci = ci, ci.adj = ci.adj, Call = cl) class(result) <- c("psych", "corr.test") return(result) }  Edit note: if the correlation coefficient is -1 or 1, your results are by DEFAULT statistically significant, because R correlation coefficient is at its maximum value. When it equals zero, then the result is not statistical significant. Therefore, maybe this function that I made of, it may not be of use. • Correlating two observations makes no sense to me. The correlation is going to be$\pm 1\$. Perhaps what you want to consider is something about how likely it is that you have positive correlation given the slope between your two points.
– Dave
Aug 10, 2020 at 18:46